前言
众所周知在JavaScript也有类的概念,但是JavaScript中的类不同于其他语言(java、c++等)的类。在那些面向类的语言中,类继承的本质是复制;而在JavaScript中严格来说并没有真正的类,它的类继承的方式比较特别,是通过原型链接来继承的,也就是说在实现类继承之后,再对父类的原型对象上的方法进行修改,子类也同样会受到影响。
好了,了解到了JavaScript不同于其他面向类的语言的独特的继承方式了,现在来聊聊JavaScript如何实现继承。这也是面试常考的一个重点,大家务必全部阅读完。
继承方式
1.原型链继承
function Cat(){ }
function Animal(){}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true
介绍: 在这里我们可以看到 new 了一个空对象,这个空对象指向 Animal 并且 Cat.prototype 指向了这个空对象,这种就是基于原型链的继承。
特点: 基于原型链,既是父类的实例,也是子类的实例
缺点: 无法实现多继承
2.构造继承
function Animal(){}
function Cat(name){Animal.call(this);this.name = name || 'Tom';}// Test Codevar cat = new Cat();console.log(cat.name);//Tomconsole.log(cat instanceof Animal); // falseconsole.log(cat instanceof Cat); // true
介绍: 使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给 子类(没用到原型)
特点: 可以实现多继承
缺点: 只能继承父类实例的属性和方法,不能继承原型上的属性和方法。
3.组合继承
function Animal(){}
function Cat(name){Animal.call(this);this.name = name || 'Tom';}Cat.prototype = new Animal();Cat.prototype.constructor = Cat;// Test Codevar cat = new Cat();console.log(cat.name);//Tomconsole.log(cat instanceof Animal); // trueconsole.log(cat instanceof Cat); // true
介绍: 相当于构造继承和原型链继承的组合体。通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
特点: 可以继承实例属性/方法,也可以继承原型属性/方法
缺点: 调用了两次父类构造函数,生成了两份实例
4.寄生组合继承
function Animal(){}
function Cat(name){Animal.call(this);this.name = name || 'Tom';}(function(){// 创建一个没有实例方法的类var Super = function(){};Super.prototype = Animal.prototype;//将实例作为子类的原型Cat.prototype = new Super();})();// Test Codevar cat = new Cat();console.log(cat.name);//Tomconsole.log(cat instanceof Animal); // trueconsole.log(cat instanceof Cat); //true
介绍: 通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的 构造的时候,就不会初始化两次实例方法/属性,解决了组合继承的缺陷
优点: 寄生组合式继承的高效率体现在它只调用了一次父类型构造函数,避免了创建不必要的或多余的属性,与此同时,原型链还能保持不变。
推荐: 推荐使用该方式来实现继承,这也是目前来说最理想的继承方式了
还有两种是在其他博主那学习过来的,现在适用性不强,主要推荐使用寄生组合继承,大家可以了解一下:
5.原型式继承
function Animal(o) {function F() {}F.prototype = o;return new F();
}
var person = {name : 'wuyuchang',friends : ['wyc', 'Nicholas', 'Tim']
}
var anotherPerson = Animal(person);
anotherPerson.name = 'Greg';
anotherPerson.friends.push('Bob');
var anotherPerson2 = Animal(person);
anotherPerson2.name = 'Jack';
anotherPerson2.friends.push('Rose');
console.log(person.friends);// [ 'wyc', 'Nicholas', 'Tim', 'Bob', 'Rose' ]
介绍: 原型式继承的的实现方法与普通继承的实现方法不同,原型式继承并没有使用严格意义上的构造函数,而是借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。
6.寄生式继承
/* 原型式继承 */
function Animal(o) {function F() {}F.prototype = o;return new F();
}
/* 寄生式继承 */
function createAnother(original) {var clone = Animal(original);clone.sayHi = function() {console.log('hi');}return clone;
}
var person = {name : 'wuyuchang',friends : ['wyc', 'Nicholas', 'Rose']
}
var anotherPerson = createAnother(person);
anotherPerson.sayHi();//hi
最后
整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。
有需要的小伙伴,可以点击下方卡片领取,无偿分享