深色模式
原型链和继承
JS 的继承是基于原型的,即使是 ES6 增加的 class 字段,也是原型的语法糖。
参考: MDN 继承
当谈到继承,JS 就只有一种数据结构 Object, 几乎所有的 JS 对象都是最顶端 Object 的实例。
原型链继承
原理: 每个对象objA
都有一个私有属性__proto__
指向 构造函数FuncA
的原型对象 prototype
, 即 FuncA.prototype
, 而该原型对象又有自己的原型对象 __proto__
, 层层向上知道一个对象的原型是 null, 如此形成了原型链。
js
function FuncA() {console.log('FuncA')};
var objA = new FuncA();
objA.__proto__ === FuncA.prototype;
FuncA.prototype.__proto__ === Object.prototype;
Object.prototype.__proto__ === null;
原型链继承属性
JS对象 obj 访问属性 p , 会从自身查找,如果没有属性,会在其原型链上查找,直到找到属性p, 或者找到原型链顶端。
js
function FuncA() {
this.a = 1;
this.b = 2;
}
const o = new FuncA();
console.log(o.a); // 1;
// 在原型链上定义属性
FuncA.prototype.b = 3;
FuncA.prototype.c = 4;
// {a: 1, b: 2} --> {b: 3, c: 4} --> Object.prototype --> null
// 自身属性,屏蔽原型链上属性 b
console.log(o.b); // 2;
// 原型链上查找到属性
console.log(o.c); // 4
// 自身和原型链上查找不到的属性
console.log(o.d); // undefined
上面的 原型链是 {a: 1, b: 2} --> {b: 3, c: 4} --> Object.prototype --> null
原型链继承方法
JS 中函数 FuncA
有一个默认属性 prototype
, 其中 FuncA()
称作构造函数, FuncA.prototype.constructor
指向 FuncA()
和属性继承一样,方法也可以继承,注意其中的 this 指向。
js
FuncA.prototype.print = function () {
console.log(this.b);
};
o.print(); // 2
FuncA.prototype.print(); // 3
常见对象和生成原型链
S 语法中创建对象
js
var o = {a: 1}
// o --> Object.prototype --> null
var arr = []
// arr --> Array.prototype --> Object.prototype --> null
function FuncA() {
}
var f = new FuncA();
// f --> FuncA.prototype --> Function.prototype --> Object.prototype --> null
构造器 prototype
js
function FuncB() {
this.a = 1;
}
FuncB.prototype = {
print() {
console.log(this.a);
},
};
const b = new FuncB();
console.log(b.print());
Object.create 创建对象
建议开发中使用 Object.create 替换掉使用 __proto__
属性
js
const c = Object.create({ m: 1 });
// c --> {m: 1} --> Object.prototype --> null
console.log(c);
console.log(c.m);
使用Class
js
"use strict";
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
class Square extends Polygon {
constructor(sideLength) {
super(sideLength, sideLength);
}
get area() {
return this.height * this.width;
}
set sideLength(newLength) {
this.height = newLength;
this.width = newLength;
}
}
var square = new Square(2);