面试题答案
一键面试原型链继承的缺陷
- 共享属性问题:
- 分析:在原型链继承中,所有实例会共享原型对象上的属性和方法。如果原型对象上的某个属性是引用类型(如数组、对象),那么当其中一个实例对该属性进行修改时,其他实例的该属性也会受到影响。例如:
function Parent() { this.names = ['John', 'Jack']; } function Child() {} Child.prototype = new Parent(); let child1 = new Child(); let child2 = new Child(); child1.names.push('Tom'); console.log(child2.names); // 输出: ['John', 'Jack', 'Tom']
- 解决方案:可以通过使用构造函数绑定(借用构造函数)来避免共享引用类型属性。
- 子类无法向父类传参:
- 分析:在原型链继承中,由于
Child.prototype = new Parent()
这种方式,在创建子类实例时,无法向父类构造函数传递参数。比如父类构造函数需要接收一些初始化参数时,原型链继承就无法满足。 - 解决方案:同样可以使用借用构造函数的方式,在子类构造函数内部调用父类构造函数并传递参数。
- 分析:在原型链继承中,由于
优化解决方案及代码示例
- 借用构造函数(解决共享属性和传参问题):
function Parent(name) { this.name = name; this.names = ['John', 'Jack']; } function Child(name, age) { // 借用构造函数,向父类传参 Parent.call(this, name); this.age = age; } // 修复原型关系 Child.prototype = Object.create(Parent.prototype); Child.prototype.constructor = Child; let child = new Child('Tom', 20); child.names.push('Bob'); let anotherChild = new Child('Jerry', 22); console.log(anotherChild.names); // 输出: ['John', 'Jack'] console.log(child.name); // 输出: 'Tom' console.log(child.age); // 输出: 20
- 组合继承(融合原型链继承和借用构造函数继承的优点):
function Parent(name) { this.name = name; this.hobbies = ['reading', 'traveling']; } Parent.prototype.sayName = function() { console.log('My name is'+ this.name); }; function Child(name, age) { Parent.call(this, name); this.age = age; } Child.prototype = Object.create(Parent.prototype); Child.prototype.constructor = Child; Child.prototype.sayAge = function() { console.log('My age is'+ this.age); }; let child1 = new Child('Alice', 25); let child2 = new Child('Bob', 28); child1.hobbies.push('swimming'); console.log(child2.hobbies); // 输出: ['reading', 'traveling'] child1.sayName(); // 输出: My name is Alice child1.sayAge(); // 输出: My age is 25