# 关于Javascript继承
整理记录一下js关于继承的基础知识点, 更多的只是基础知识点的总结。
首先通过一个图,了解下原型和原型链
简单来说就是每一个构造函数都有一个prototype属性,指向构造函数的原型对象
每个js对象, 除了null,都有一个__proto__
属性指向对象的原型
原型也有constructor属性指向关联的构造函数
由图中__proto__
组成的蓝色链状结构就是原型链
# 1.原型链继承
function Parent() {
this.name = 'your father';
}
Parent.prototype.getName = function () {
return this.name;
};
function Child() {}
Child.prototype = new Parent();
const child = new Child();
console.log(child.getName()); // 'your father'
const child2 = new Child();
console.log(child2.getName()); // 'your father'
存在的问题是:
- 引用类型的属性被所有的实例共享
- 无法给父类传参
# 2.借用构造函数
function Parent () {
this.names = ['p1', 'p2'];
}
function Child () {
Parent.call(this);
}
优点
- 避免了引用类型的属性被所有实例共享
- 可以在 Child 中向 Parent 传参
缺点
- 方法都在构造函数中定义,每次创建实例都会创建一遍方法。
# 3.组合继承
原型链继承和经典继承的组合
function Parent(name) {
this.name = name;
this.sex = 1;
}
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
优点:融合原型链继承和构造函数的优点,是 JavaScript 中最常用的继承模式。
缺点: 多次调用父构造函数
# 4.寄生组合式继承
function Parent (name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
Parent.prototype.getName = function () {
console.log(this.name)
}
function Child (name, age) {
Parent.call(this, name);
this.age = age;
}
// 关键的三步
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
var child1 = new Child('kevin', '18');
相对比较完善的继承方式
# 5. es6 class继承
class Animal {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
class Cat extends Animal {
constructor(name, age) {
super(name);
this.age = age;
}
getInfo() {
return this.name + ' ' + this.age;
}
}
const a = new Cat('cat', 1);
console.log(a.getName());
简单了解下, 深入的话其实还是有内容不少
# 补充知识
# proto
__proto__
实际上来自于 Object.prototype
, 使用obj.__proto__
可以理解成使用了Object.getPrototypeOf(obj)
# instanceof
instanceof
运算符用于检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上。
可以模拟实现一个instanceOf
function instanceOf(instance, Constructor) {
let ctorPrototype = Constructor.prototype; // 取右表达式的 prototype 值
instance = instance.__proto__; // 取左表达式的__proto__值
while (true) {
if (instance === null) {
return false;
}
if (instance === ctorPrototype) {
return true;
}
instance = instance.__proto__;
}
}