prototype
1. prototype和__proto__
function Foo() {
...
}
Foo.prototype.constructor === Foo; // true
let foo = new Foo();
foo.constructor === Foo; // true
例如,当声明一个函数Foo的时候,会默认给这个函数的prototype添加一个constructor属性,并且指向Foo函数本身。
但是,函数Foo的实例对象foo,它的身上是没有constuctor这个属性的,这里foo是通过原型找到该属性的,即foo.proto.constructor,其实foo.__proto__
就是指向了Foo.prototype
,即foo.__proto__ === Foo.prototype; // true
foo.constructor === Foo; // true
foo.hasOwnProperty('constructor'); // false
foo.__proto__.hasOwnProperty('constructor'); // true
Foo.hasOwnProperty('constructor'); // false
Foo.prototype.hasOwnProperty('constructor'); // true
// 因为
foo.__proto__ === Foo.prototype; // true
2. __proto__和prototype的关系
__proto__
: JS每个对象内部都隐含了一个__proto__属性,用来指向它的原型对象,即xxx.prototype。
例如对象a:let a = {name: "example"}
prototype
: 与__proto__不同的是,这个属性只有函数才有。并且添加到prototype上的属性和方法在所有实例中都是共享的。譬如Foo.prototype,可以看到Foo.prototype中也有__proto__属性,指向它的原型对象。
3. 使用prototype实现继承
通过原型很容易实现对象间的继承,JS中继承是通过委托机制实现的。最常用的一种方式是通过Object.create(..)
方法。
function Foo() {
this.name = "Foo";
}
Foo.prototype.sayName = function () {
return "This is " + this.name;
}
function Bar() {
this.name = "Bar";
}
// 让Bar继承Foo
Bar.prototype = Object.create(Foo.prototype);
let bar = new Bar();
bar.sayName(); // This is Bar
// 此时 bar.__proto__ -> Bar.prototype -> Foo.prototype -> Object.prototype -> null
bar.__proto__ === Foo.prototype; // true
Object.getPrototypeOf(bar) === Bar.prototype; // true
通过Object.create(..)
方法,让Bar
的原型链指向Foo
的原型实现继承效果。如图所示:
4. 对象关联
如果要使两个对象关联起来,比如让对象bar关联对象foo, 同样使用Object.create()
方法
function Foo() {
this.name = "Foo";
}
Foo.prototype.sayName = function () {
return "This is " + this.name;
}
function Bar() {
this.name = "Bar";
}
// 让Bar继承Foo
Bar.prototype = Object.create(Foo.prototype);
let bar = new Bar();
bar.sayName(); // This is Bar
// 此时,bar.__proto__ -> foo -> Foo.prototype -> Object.prototype -> null
Object.getPrototypeOf(bar) === Bar.prototype; // false
Object.getPrototypeOf(bar) === foo; // true
这里仅仅是两个对象的关联!因此不仅可以调用Foo.prototype原型上的方法,也可以调用foo对象上的方法。如图
5. 获取原型链
- 直接通过
foo.__proto__
- 通过
Object.getPrototypeOf(foo)