面试题答案
一键面试实际应用中可能出现的场景
- 全局库的原型修改:
- 假设项目中使用了一个第三方库,该库在全局对象(如
Object.prototype
)上添加了一些方法。如果后续代码不小心再次修改了这个全局原型,例如:
- 假设项目中使用了一个第三方库,该库在全局对象(如
// 第三方库代码
Object.prototype.customMethod = function() {
return 'This is a custom method';
};
// 项目其他代码
Object.prototype.customMethod = function() {
return 'This is a wrong custom method';
};
- 这样所有依赖`Object.prototype.customMethod`的实例和代码都会受到影响,原本期望的行为被改变,可能导致整个项目中依赖此方法的功能出错。
2. 子类继承后的原型误操作:
- 考虑一个简单的继承结构,有一个Animal
类和它的子类Dog
。
function Animal() {}
Animal.prototype.speak = function() {
console.log('I am an animal');
};
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
// 开发者在操作Dog实例时,意外修改了Dog的原型
Dog.prototype.speak = function() {
console.log('I am a wrong dog');
};
const dog1 = new Dog();
const dog2 = new Dog();
dog1.speak(); // 输出 'I am a wrong dog'
dog2.speak(); // 输出 'I am a wrong dog'
// 原本期望的Dog类的speak方法行为被改变,可能影响到整个项目中Dog类实例的使用
避免安全隐患的措施
- 使用ES6类继承:
- ES6的
class
语法在继承时更加清晰和安全。
- ES6的
class Animal {
speak() {
console.log('I am an animal');
}
}
class Dog extends Animal {
constructor() {
super();
}
// 如果要覆盖speak方法,明确在这里进行操作
speak() {
console.log('I am a dog');
}
}
- 通过`class`关键字定义类和继承关系,使得代码结构更清晰,减少意外修改原型的可能性。同时,`class`语法在内部处理原型链时遵循严格的规则,降低了因不当操作原型而引发问题的风险。
2. 冻结原型: - 在子类继承后,可以冻结原型,防止意外修改。
function Animal() {}
Animal.prototype.speak = function() {
console.log('I am an animal');
};
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
// 冻结Dog的原型
Object.freeze(Dog.prototype);
// 尝试修改会失败,严格模式下会抛出错误
Dog.prototype.speak = function() {
console.log('I am a wrong dog');
};
- `Object.freeze`方法可以使对象不可扩展,即不能再添加新的属性,且现有属性的特性也不能被改变,包括不能修改属性值。这样可以有效避免意外修改原型导致的行为改变。
3. 使用闭包封装: - 通过闭包来封装类和原型的定义,减少全局作用域的暴露。
const AnimalModule = (function() {
function Animal() {}
Animal.prototype.speak = function() {
console.log('I am an animal');
};
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
return {
Dog: Dog
};
})();
const dog = new AnimalModule.Dog();
// 这里外部代码无法直接访问和修改Animal和Dog的原型,降低了安全隐患
- 在闭包内部定义类和原型,只暴露需要的部分(如`Dog`类),这样可以避免外部代码意外修改原型。因为外部代码无法直接访问闭包内部的变量和原型,只有通过暴露的接口来操作,从而提高了安全性。