1、JS 中的继承
当谈到继承时,JavaScript 只有一种构造:对象。每个实例对象(object)都有一个公有属性(称之为 proto)指向它的构造函数的原型对象(prototype)。
该原型对象也有一个本人的原型对象(__proto__),层层向上直到一个对象的原型对象为
null
。依据定义,null
没有原型,并作为这个 原型链 中的最初一个环节。
2、继承属性
JavaScript 对象是动静的属性“包”(指其本人的属性)。JavaScript 对象有一个指向一个原型对象的链。
当试图拜访一个对象的属性时,它不仅仅在该对象上搜查,还会搜查该对象的原型,以及该对象的原型的原型,顺次层层向上搜寻,直到找到一个名字匹配的属性或达到原型链的开端。
3、创立原型链的 Demo
// 让咱们从一个函数里创立一个对象 o,它本身领有属性 a 和 b 的:let f = function () {
this.a = 1;
this.b = 2;
}
/* 这么写也一样
function f() {
this.a = 1;
this.b = 2;
}
*/
let o = new f(); // {a: 1, b: 2}
// 在 f 函数的原型上定义属性
f.prototype.b = 3;
f.prototype.c = 4;
// 不要在 f 函数的原型上间接定义 f.prototype = {b:3,c:4}; 这样会间接突破原型链
// o.[[Prototype]] 有属性 b 和 c
// (其实就是 o.__proto__ 或者 o.constructor.prototype)
// o.[[Prototype]].[[Prototype]] 是 Object.prototype.
// 最初 o.[[Prototype]].[[Prototype]].[[Prototype]]是 null
// 这就是原型链的开端,即 null,// 依据定义,null 就是没有 [[Prototype]]。// 综上,整个原型链如下:
// {a:1, b:2} ---> {b:3, c:4} ---> Object.prototype---> null
console.log(o.a); // 1
// a 是 o 的本身属性吗?是的,该属性的值为 1
console.log(o.b); // 2
// b 是 o 的本身属性吗?是的,该属性的值为 2
// 原型上也有一个 'b' 属性,然而它不会被拜访到。// 这种状况被称为 "属性遮蔽 (property shadowing)"
console.log(o.c); // 4
// c 是 o 的本身属性吗?不是,那看看它的原型上有没有
// c 是 o.[[Prototype]]的属性吗?是的,该属性的值为 4
console.log(o.d); // undefined
// d 是 o 的本身属性吗?不是,那看看它的原型上有没有
// d 是 o.[[Prototype]] 的属性吗?不是,那看看它的原型上有没有
// o.[[Prototype]].[[Prototype]] 为 null,进行搜寻
// 找不到 d 属性,返回 undefined