[[Prototype]]定义一个对象,当访问对象内属性时,可以找到就可以相当于调用的是对象
[[GET]]方法,找到属性对应的值,当找不到属性时,这个时候就会去寻找[[Prototype]]链上的属性了,如果还是找不到那就会继续在链上找[[Prototype]],从而继续查找,直到查找完整个链,最终如果还是未曾找到,那么就会返回undefined。如:
function Person(){
this.name = 'Lee';
}
Person.prototype.age = 18;
var person = new Person();
console.log(person); // Person { name: "Lee", [[Prototype]]: { age: 18 } }
console.log(person.name); // Lee
console.log(person.age); // 18
console.log(person.sex); // undefined
Object.prototype内置
[[Prototype]]链最终都会指向Object.prototype,它包含了js中许多通用的功能(如:toString、hasOwnProperty等)
function Person(){}
Person.prototype.name = 'Tom';
var person = new Person();
console.log(person.name); // Tom
person.name = 'Lee';
console.log(person); // Person { name: "Lee", [[Prototype]]: { name: "Tom" } }
console.log(person.name); // Lee
function Person(){
this.name = 'Lee';
}
Person.prototype.name = 'Tom';
var person = new Person();
console.log(person.name); // Lee
针对
person.name = 'Lee';的三种情况
writable值为true或false时
writable = truefunction Person(){}
Object.defineProperty(Person.prototype, 'name', {
value: 'Tom',
writable: true
})
var person = new Person();
person.name = 'Lee';
console.log(person); // Person { name: "Lee", [[Prototype]]: { name: "Tom" } }
console.log(person.name); // Lee
writable = falsefunction Person(){}
Object.defineProperty(Person.prototype, 'name', {
value: 'Tom',
writable: false
})
var person = new Person();
person.name = 'Lee';
console.log(person); // Person { [[Prototype]]: { name: "Tom" } }
console.log(person.name); // Tom
setter属性时function Person() { }
var _name = 'Tom';
Object.defineProperty(Person.prototype, 'name', {
get: () => _name,
set: value => _name = value
})
var person = new Person();
console.log(person.name); // Tom
person.name = 'Lee';
console.log(person); // Person { name: "Lee", [[Prototype]]: { name: "Lee" } }
console.log(person.name); // Lee

调用
new Person()时会创建person,其中一部就是给person一个内部的[[Prototype]]链接,关联到Person.prototype指向的那个对象。
function Person() { this.name = 'Lee'; }
var person = new Person();
console.log(Person.prototype); // { constructor: ƒ Person() }
console.log(Object.getPrototypeOf(person)); // { constructor: ƒ Person() }
console.log(Object.getPrototypeOf(person) === Person.prototype); // true
一个类可以实例化多个对象,但多个对象的
[[Prototype]]关联的实际上是同一个对象,因此这些对象并不是完全失去联系的,他们是相互关联着的。
function Person() { this.name = 'Lee'; }
var lee = new Person();
var tom = new Person();
console.log(Object.getPrototypeOf(lee) === Object.getPrototypeOf(tom)); // true
原型继承function Foo(){ this.name = "Foo"; }
function Bar(){ this.age = 18; }
Bar.prototype = Foo; // Bar 继承 Foo
var foo = new Foo();
var bar = new Bar();
console.log(bar.name); // Foo
console.log(Object.getPrototypeOf(bar)); // ƒ Foo(){ this.name = "Foo"; }
委托访问另一个对象的的属性和函数。我们认为
Person是一个类的原因是因为我们使用了关键词new,实际上我们的构造函数指向的是原型属性.constructor上的值。如下示例:
function Foo() { }
console.log(Foo.prototype.constructor); // ƒ Foo() { }
var foo = new Foo();
console.log(foo.constructor); // ƒ Foo() { }
console.log(Object.getPrototypeOf(foo)); // {constructor: ƒ Foo()}
function Person() { }
Person.prototype.constructor = null;
var person = new Person();
console.log(person.constructor); // null
console.log(Object.getPrototypeOf(person)); // {constructor: null}
函数不是构造函数,但是当使用new修饰时,函数调用就会变成构造函数调用this.name = name;为每个对象添加了一个name属性foo1.say()没有在但前对象上找到函数,就会通过委托去Foo原型上去寻找function Foo(name) { this.name = name; }
Foo.prototype.say = function(){
return this.name;
}
var foo1 = new Foo('Lee');
var foo2 = new Foo('Tom');
console.log(foo1, foo1.say()); // Lee
console.log(foo2, foo2.say()); // Tom
四种继承方式function FunA(a) {
this.a = a;
}
FunA.prototype.logA = function () {
console.log(this.a);
}
function FunB(b) {
this.b = b;
}
FunB.prototype.logB = function () {
console.log(this.b);
}
FunB.prototype = Object.create(FunA.prototype);
// FunB.prototype = FunA.prototype;
// FunB.prototype = new FunA('aaa');
// Object.setPrototypeOf(FunB.prototype, FunA.prototype);
console.log(FunB.prototype);
FunB.prototype = Object.create(FunA.prototype);
FunB.prototype 对象并把它关联到 FunA.prototypeFunB.prototype = FunA.prototype;
FunB.prototype 的新对象,他只是让 FunB.prototype 直接引用 FunA.prototype 本身FunB.prototype = new FunA();
FunB.prototype 的新对象,但是它使用的是 FunA 的 构造函数调用,如果 FunA 本身存在一些 副作用(如写日志、修改状态、注册到其他对象、给this添加数据属性,等等) 的话,就会影响到 FunB 的后代,后果不堪设想Object.setPrototypeOf(FunB.prototype, FunA.prototype);
Object.create 会抛弃之前的 FunB.prototype 创建一个新的对象Object.setPrototypeOf 会直接修改现有的 FunB.prototypeinstanceof
isPrototypeOf
Object.getPrototypeOf
__proto__(不推荐)
如果在对象上没有找到需要的属性或者方法引用,引擎就会继续在
[[Prototype]]关联的对象上进行查找。同理,如果在后者中也没有找到需要的 引用就会继续查找它的[[Prototype]],以此类推。这一系列对象的链接被称为“原型链”。
Object.create() 的 polyfill 代码(兼容写法)// Object.create() 的 polyfill 代码
if (!Object.create) {
Object.create = function (o) {
function F() { }
F.prototype = o;
return new F();
}
}