龙空技术网

大厂高频面试题:JavaScript继承

尚硅谷教育 162

前言:

此时小伙伴们对“js原型原型链继承面试题”大体比较关切,我们都想要了解一些“js原型原型链继承面试题”的相关文章。那么小编也在网上搜集了一些对于“js原型原型链继承面试题””的相关文章,希望我们能喜欢,我们一起来学习一下吧!

大家好,今天我来带大家深入学习一下JS面向对象三大特性——继承

一、什么是继承?

继承是面向对象中最重要的一个概念,或者说特性。

在JS语言中,继承主要是利用构造函数以及原型链实现继承效果。它可以让子类对象(实例)使用父类的所有属性以及方法,并且可以直接在子类上扩展新的属性或方法。

使用继承可以提高我们代码的复用性,从而减少我们的代码量,降低开发成本。

二、编码实现JS继承

接下来我们主要讲讲JS继承最常用的四种方法——原型链继承,借用构造函数继承,原型链和构造函数组合式继承以及ES6提供给我们的基于class类的继承。

2.1原型链继承

原理:

将子类的原型对象指向父类的实例,再将子类的原型的构造器补充完整。

技术重点:

①让子类的原型指向父类的实例:

Student.prototype=new Person();

②让子类原型的构造器指向子类本身:

Student.prototype.constructor=Student。

编码实现:

//父类

function Person() {

this.name = "Tom";

this.age = 18;

}

Person.prototype.call = function () {

console.log(`我叫${this.name}, 今年${this.age}岁`);

};

//子类

function Student() {}

//原型继承

Student.prototype = new Person();

Student.prototype.constructor = Student;

//实例化子类对象

var s = new Student();

console.log(s.name); // Tom

console.log(s.age); // 18

s.call(); // 我叫Tom, 今年18岁

优点:

子类可以继承父类所有的属性以及方法。

缺点:

①子类的所有实例共享父类的属性,对引用类型数据的修改会影响其他的实例。

②在创建子类实例时,不能向父类的构造函数传递参数。

2.2借用构造函数继承

原理:

在子类的构造函数内部使用apply或者call方法调用父类的构造函数,继承父类的属性。

技术重点:

借用父类型的构造函数,继承父类的属性:

Person.call(this,name,age)

编码实现:

//父类

function Person(name, age) {

this.name = name;

this.age = age;

}

Person.prototype.call = function () {

console.log(`我叫${this.name}, 今年${this.age}岁`);

};

//子类

function Student(name, age) {

// 借用父类的构造函数

Person.call(this, name, age);

}

//实例化子类对象

var s = new Student("Jerry", 20);

console.log(s.name); // Jerry

console.log(s.age); // 20

s.call(); // 报错

优点:

①父类的引用属性不会被共享。

②子类的实例可以向父类传递参数。

缺点:

不能继承原型属性,父类的方法不能复用,所有的方法只能放在构造函数内部。

2.3组合式继承

原理:

利用构造函数继承和原型链的组合实现继承,解决了他们单独使用时出现的问题。

技术重点:

①借用父类型的构造函数,继承父类的属性:

Person.call(this,name,age)

②让子类的原型指向父类的实例:

Student.prototype=new Person()

③让子类原型的构造器指向子类本身:

Student.prototype.constructor=Student

编码实现:

// 父类型

function Person(name, age) {

this.name = name;

this.age = age;

}

Person.prototype.fn = function () {};

Person.prototype.sayHello = function () {

console.log(`我叫${this.name}, 今年${this.age}岁`);

};

// 子类型

function Student(name, age, score) {

// 借用父类型的构造函数

Person.call(this, name, age);

this.score = score;

}

// 让子类的原型为父类的实例

Student.prototype = new Person();

// 让原型对象的构造器为子类型

Student.prototype.constructor = Student;

Student.prototype.sayHello = function () {

console.log(

`我叫${this.name}, 今年${this.age}岁, 考了${this.score}分`

);

};

const s = new Student("tom", 23, 95);

s.sayHello(); // 我叫tom, 今年23岁, 考了95分

s.fn();

优点:

解决了原型链继承和借用构造函数继承造成的影响。

①父类的方法可以复用。

②父类的引用数据类型属性不会被共享。

③子类创建实例时可以向父类传参。

缺点:

调用了两次父类的构造函数,一次在创建子类的原型时,另一次在子类构造函数内部。造成的性能上的浪费。

2.4class类的继承

原理:

利用ES6提供的新语法class类实现继承。

技术重点:

①子类extends(继承)父类:

class Teacher extends Person

②子类构造器中调用父类的构造函数:

super(name, age)

编码实现:

// 父类

class Person2 {

constructor(name, age) {

this.name = name;

this.age = age;

}

fn() {}

sayHello() {

console.log(`我叫${this.name}, 今年${this.age}岁`);

}

}

// 子类

class Teacher extends Person2 {

constructor(name, age, course) {

super(name, age);

this.course = course;

}

// 重写父类的方法

sayHello() {

console.log(

`我叫${this.name}, 今年${this.age}岁, 教${this.course}`

);

}

}

const t = new Teacher("jack", 34, "English");

t.sayHello(); // 我叫jack, 今年34岁, 教English

t.fn();

优点:

语法简单易懂,操作更方便。

缺点:

存在兼容性问题,不是所有的浏览器都支持。

三、结尾

好了,以上就是为大家总结的关于JS继承的编码实现原理以及方法,希望看完这篇文章后大家再也不会对继承问题感到困惑。

标签: #js原型原型链继承面试题