Javascript 创建“类”和对象
接触过像 C++ Java 这样的编程语言,对面向对象编程一定不陌生。面向对象编程的两个核心是类和对象。
类是一种数据结构(事物)的描述、生成对象的模板,而对象是根据描述创建的实体。
如果说面向对象,Javascript 则更加“忠诚”,因为它根本就没有类,所谓“类”只是一个构造器,一个函数。在 JS 中,万物皆为对象,函数也是对象。JS 可以模拟类和对象的行为,让编程就像面向对象编程一样。JS 面向对象编程的实现是用函数,作用域劫持和闭包“凑活”出来的。说了这么多学院理论,Let's make our hands wet!
创建一个学生类,有姓名和学号属性和打招呼(say)方法
function Student(name, id) {
this.name = name
this.id = id
}
Student.prototype.say = function() {
console.log('Hello, I am ' + this.name)
}
var jack = new Student('Jack', 1210)
jack.say() //Hello, I am Jack
让我们看看这七句话都做了哪些事。
在 JS 中,每个对象都有一个__proto__
内置属性,这里面存放了一个指向对象原型
的引用(指针),此例中是Student.prototype
。.prototype
可以认为是Student
对象的一个属性。对象原型这个属性 Student.prototype
下面可以挂一些公共方法或者属性(可以先理解为静态方法,静态成员变量)new Student
中的new
都做了那些事情
- 创建一个空对像
var obj = {}
- 将刚才创建对象pbj的
__proto__
属性设置为Student.prototype
obj.__proto__ = Student.prototype
Student.call(obj)
把Student
的作用域劫持到obj
对象上并执行,此时Student
函数里面的this指向obj- 将
obj
返回return obj
jack 变量接收返回的 objjack.say()
当访问一个对象的属性或者方法时,查找顺序依据原型链,jack的原型链是
jack--->Student.prototype--->Object.prototype--->null
在jack
对象中并没有say
这个方法,于是向上查找,在其对象原型(通过__proto__
属性找到对象原型)下找到该方法的定义然后执行
Q & A
为什么不把方法放到Student
构造器里面?
这样每当创建一个实例,就会生成一个say方法(或者说属性)这些say方法的逻辑都一样,但是却占用了多份空间,对性能产生影响。var jessie = new Student('Jessie', 14512)
jack.say === jessie.say //false
可不可以手动改变一个对象的__proto__
?
不要手动这样做!不要手动这样做!不要手动这样做!
jack.__proto__.__proto___
jack.__proto__
是Student.prototype
,Student.prototype.__proto
是Object.prototype
。熟悉 Java 的同学可能知道,Java 里面所有的类都继承自 Object 类,Object 是所有类的老祖宗。而Object.prototype
是所有对象的原型,换句话说,所有对象都可以调用Object.prototype
下面的方法。
例如Student.prototype.isPrototypeOf(jessie)//true
其中isPrototypeOf(jessie)
就是Object.prototype
下面的方法
结束语
Javascript 是一门很灵活也有很多坑的语言。本身的设计也有不少缺陷。如果有些灵活过头的特性,不如把它加入黑名单,不去使用它,比如手动修改__proto__
这种做法。在 Javascript 中很多原则是人为规定,并不是强制的。在写代码的过程中尽量遵守,以免造成麻烦。
除非注明,嗯VIEW文章均为原创,转载请以链接形式标明本文地址
本文地址:https://www.umview.com/javascript-prototype-obj
还不快抢沙发