整理了一些js继承相关的内容,如有看到这篇文章的同学,不对的地方还望指出
使用call或apply继承(构造继承)
call和apply的作用是一样的,都是改变一个函数运行时this的指向,只是两者接受的参数有些差别,这里就不多说了。
function parent() {
this.name = 'Aiden';
this.say = function (){
console.log(this.name);
}
}
function child() {
parent.call(this);
this.age = 17;
}
var kid = new child();
kid.say(); //Aiden
这种继承有一个缺点,child无法继承parent的原型对象,仅仅实现部分继承,如下。
function parent() {
this.name = 'Aiden';
this.say = function (){
console.log(this.name);
}
}
parent.prototype.sayHello = function () {
console.log('Hello');
};
function child() {
parent.call(this);
this.age = 17;
}
var kid = new child();
kid.sayHello(); // Uncaught TypeError: kid.sayHello is not a function
使用prototype继承(原型链继承)
将parent的实例作为child的原型
function parent() {
this.name = 'Aiden';
this.say = function (){
console.log(this.name);
}
}
function child() {
this.age = 17;
}
child.prototype = new parent();
var kid = new child();
kid.say(); // Aiden
这种方式解决了上文中继承不完全的问题
function parent() {
this.name = 'Aiden';
this.say = function (){
console.log(this.name);
}
}
function child() {
this.age = 17;
}
parent.prototype.sayHello = function(){
console.log('Hello');
};
child.prototype = new parent();
var kid = new child();
kid.say(); // Aiden
kid.sayHello(); // Hello
这种方法解决了一个问题的同时衍生出了另一个问题。参考下面代码,运行结果和期望结果并不一致。
这是因为kidA和kidB继承的数组arr共用了同一块内存,push操作和赋值不一样,不会重新分配内存,所以导致了这个结果,也就是说kidA和kidB没有真正意义上的隔离。
function parent() {
this.name = 'Aiden';
this.arr = [1,2,3];
this.say = function (){
console.log(this.name);
}
}
function child() {
this.age = 17;
}
child.prototype = new parent();
var kidA = new child();
kidA.name = 'Tom';
kidA.arr.push(4);
var kidB = new child();
console.log(kidA.name); // Tom
console.log(kidA.arr); // [1,2,3,4]
console.log(kidB.name); // Aiden
console.log(kidB.arr); // [1,2,3,4]
组合式继承
这种方式解决了上面两种的缺点
function parent() {
this.name = 'Aiden';
this.arr = [1,2,3];
this.say = function (){
console.log(this.name);
}
}
function child() {
parent.call(this);
this.age = 17;
}
child.prototype = Object.create(parent.prototype);
var kidA = new child();
kidA.name = 'Tom';
kidA.arr.push(4);
var kidB = new child();
console.log(kidA.name); // Tom
console.log(kidA.arr); // [1,2,3,4]
console.log(kidB.name); // Aiden
console.log(kidB.arr); // [1,2,3]
ES6的继承
es6多了class类的概念,可以直接使用extends继承,没有上述的这些问题。注意子类的constructor中一定要先调用super方法,否则实例化时会报错,具体可参考阮一峰老师的《ECMAScript 6 入门》。
class human {
constructor(){
this.city = 'Shanghai';
}
}
class man extends human{
constructor() {
super();
this.sex = 'male';
this.arr = [1,2,3];
}
}
class Tom extends man {
constructor(){
super();
this.name = 'Tom';
}
}
let person1 = new Tom();
console.log(person1.city); // Shanghai
console.log(person1.name); // Tom
console.log(person1.sex); // male
person1.arr.push(4); // [1, 2, 3, 4]
console.log(person1.arr);
let person2 = new Tom();
console.log(person2.arr); // [1, 2, 3]