理解js的原型链

190 阅读2分钟

前言

遵循ECMAScript标准,someObject.[[Prototype]] 符号是用于指向 someObject 的原型。从 ECMAScript 6 开始,[[Prototype]] 可以通过 Object.getPrototypeOf() 和 Object.setPrototypeOf() 访问器来访问。这个等同于 JavaScript 的非标准但许多浏览器实现的属性 __proto__。 但它不应该与构造函数 func 的 prototype 属性相混淆。被构造函数创建的实例对象的 [[Prototype]] 指向 func 的 prototype 属性。Object.prototype 属性表示 Object 的原型对象。

  • 注意: 不同的浏览器,输出的__proto__也不一样, [[Prototype]]__ proto__ 是一个东西, 在火狐浏览器还叫<prototype>..

1、先理解MDN这两句话

1、当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象(object)都有一个私有属性(称之为 proto )指向它的构造函数的原型对象(prototype)。

  • 用代码来理解第一句话
//构造对象Person
function Person (name){
  this.name = name
}
let personA = new Person('A') //对象personA  

console.dir(Person) //构造函数有 __proto__, prototype属性
console.log(personA) //对象有 __proto__属性
console.log(personA.__proto__ === Person.prototype) //true, 对象的__proto__指向构造函数的prototype

2、该原型对象(prototype)也有一个自己的原型对象(proto),层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。几乎所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。

  • 万物兼对象,对象顶端兼为null

image.png

2、继承

属性继承

当我们知道Person.protoType === personA.__proto__的时候,我们就可以完成继承了

//对象personA继承 构造函数的Peron

//构造函数Person
function Person (name){
  this.name = name
}
//对象personA
let personA = new Person('A') 
//给构造函数的prototype上新增两个属性country和age
Person.prototype.country = 'china'
Person.prototype.age = 0
//给对象增加age属性
personA.age = 12

console.log(personA.country) //china
console.log(personA.age) // 12 ,由此可知,对象的自己属性优先与自己__proto__的属性

总结

  • 对象先会去自己属性上找值,如果没有,就会从__proto__上找值

继承方法 摘自MDN

var o = {
  a: 2,
  m: function(){
    return this.a + 1;
  }
};

console.log(o.m()); // 3
// 当调用 o.m 时,'this' 指向了 o.

var p = Object.create(o);
// p是一个继承自 o 的对象

p.a = 4; // 创建 p 的自身属性 'a'
console.log(p.m()); // 5
// 调用 p.m 时,'this' 指向了 p
// 又因为 p 继承了 o 的 m 函数
// 所以,此时的 'this.a' 即 p.a,就是 p 的自身属性 'a' 

原型链

image.png

  • 我们只要记住,对象的__proto__永远指向他的上一级的prototype
function Fn(name) {
  this.name = name
}

let f = new Fn('David')

console.log(f.__proto__ === Fn.prototype) //true
console.log(Fn.prototype.__proto__ === Object.prototype) //true
console.log(Object.prototype.__proto__ === null) //对象兼空

参考

面不面试的,你都得懂原型和原型链

继承与原型链