Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
上节我们得知:任何对象(包括函数)都有一个__proto__属性指向原型,而函数还有一个特别的__prototype__属性,其本身是一个实例对象。我们深入探究一下。
函数的prototype属性
function A(){};
var B=function(){};
每个函数都有一个 实例对象prototype 作为该函数的属性:
A.prototype:{
constructor: ƒ A()
__proto__: Object.prototype
}
B.prototype:{
constructor: ƒ ()//B的构造器是匿名的
__proto__: Object.prototype
}
prototype实例对象必定拥有成员:
constructor,指向函数本身:A.prototype.constructor: ƒ A(){ }- 一个
__proto__属性,指向的是Object函数的prototype属性,意思是A函数的prototype的原型是Object函数的prototype;Object.prototype:{ constructor: ƒ Object() toString: ƒ toString() valueOf: ƒ valueOf() __defineGetter__: ƒ __defineGetter__() __proto__: (...) ... }
而Object的prototype就没有原型了,它的__proto__属性为null,到底了。
事情逐渐好玩了起来!为什么每个函数都要有一个prototype属性?它们是用来干什么的?
我们使用new来用函数创建实例试一试。
实例对象的原型
- 使用
new运算符创建实例a时,a的原型指向了构造函数的prototype。
function A(){
this.member1='abc';
}
var a = new A();
a:
{
member1:'abc',
__proto__:{
constructor: ƒ A()
__proto__: Object.prototype
}//这不就是构造函数的prototype属性吗!
}
也就是说,a这个实例,现在自己有一个member1成员,和一个原型。并且,实际上,a要是想调用原型中的成员,可以跨过__proto__直接调用!
a.constructor:
ƒ A(){
this.member1='abc';
}
这个其实就是JS继承机制的原理。他究竟是怎么运作的?这里埋个伏笔。
另外:
- 使用
Object.create()基于实例a创建实例b后,b的原型指向了a。
a.member1 = 123;
var b = Object.create(a);
b.__proto__: a
我拿我一开始在第一节举得衣服的例子继续解释:
也就是说,使用create方法,能给a加件衣服,令加了件衣服的a叫b,但是使用b也可以调用a的成员,b并不是从a拷贝构造出来的(忘掉C++)。
那么知道了这些,我将在下节中给大家讲述JS真正有意思的机制——原型链 。大家不要错过~