__proto__
、prototype傻傻分不清楚? 记住以下两点:1.
__proto__
是每个对象都有的一个属性,而prototype是函数才会有的属性。2.
__proto__
指向的是当前对象的原型对象,而prototype指向的,是以当前函数作为构造函数构造出来的对象的原型对象(写在最前面,转自知乎@刘狗蛋)
var Person=function(){
this.age=1;
}
Person.prototype.name="wwx";
现在来实例化一个Person
1、var b={};
2、b.__proto__=Person.prototype;
console.log(b)
console.log(b.name)
__proto__
是什么?我们在这里简单地说下。每个对象都会在其内部初始化一个属性,就是__proto__
,当我们访问一个对象的属性 时,如果这个对象内部不存在这个属性,那么他就会去__proto__
里找这个属性,这个__proto__
又会有自己的__proto__
,于是就这样 一直找下去,也就是我们平时所说的原型链的概念。3、此时我们还需要让b这个对象有age属性,这时候我们可以b.age=1; OK加上了
Oh,No!让我们来想一些东西 如果Person 有100个属性呢,我们就要100个b.xxx=YYY. 太复杂了,真的不能忍!
Person.call(b) 搞定!此时应该有疑问,为什么一个call就可以搞定呢?其内部究竟是怎么实现的?
以上其实也就是相当于 var b = new Person();
这个new究竟做了什么?我们可以把new的过程拆分成以下三步:其实也就是我们上面那三步
-
var b={}; 也就是说,初始化一个对象b。
-
b.__proto__
=Person.prototype; -
Person.call(b);也就是说构造b,也可以称之为初始化b。
思考:call 并不能call出来Person.prototype验证:
var Boy=function (){
this.sex="man";
}
Boy.prototype.hair="black";
var c={};
Boy.call(c)
console.log(c.hair) //undefined
call()的官方解释,“调用一个对象的一个方法,以另一个对象替换当前对象。”
Person.call(b); 等等Person 好像不符合 “一个对象的一个方法”,其实非也,你可以打印一下 windown.Person
练习:
附上一段官方翻译:
Each constructor is a function that has a property named “prototype” that is used to implement prototype-based inheritance and shared properties. Every object created by a constructor has an implicit reference (called the object’s prototype) to the value of its constructor’s “prototype” property.
When a constructor creates an object, that object implicitly references the constructor’s prototype property for the purpose of resolving property references. The constructor’s prototype property can be referenced by the program expression constructor.prototype, and properties added to an object’s prototype are shared, through inheritance, by all objects sharing the prototype. Alternatively, a new object may be created with an explicitly specified prototype by using the Object.create built-in function. –ECMAScript® 2015 Language Specification
每个构造函数都有一个名为“prototype”的属性,用于实现基于原型的继承和共享属性。 由构造函数创建的每个对象都有一个隐式引用(称为对象的原型),以指向其构造函数的“prototype”属性的值。
当构造函数创建一个对象时,为了解析属性引用,该对象隐式引用构造函数的prototype属性。 构造函数的prototype属性可以通过程序表达式constructor.prototype来引用,并且添加到对象原型的属性通过继承共享原型的所有对象来共享。 或者,可以使用Object.create内置函数通过显式指定的原型创建新对象。 -ECMAScript®2015语言规范