面试题答案
一键面试JavaScript 中类和原型的底层实现原理
- 类的本质:在 JavaScript 中,类是基于原型的面向对象编程的语法糖。ES6 引入的
class
关键字让 JavaScript 的面向对象编程看起来更像传统面向对象语言。但实际上,它背后仍然是基于原型的机制。 - [[Prototype]] 机制:每个对象都有一个内部属性
[[Prototype]]
,它要么为null
,要么指向另一个对象。这个属性在 JavaScript 引擎内部使用,通过Object.getPrototypeOf()
方法或__proto__
属性(非标准,不建议在生产代码中使用,但可用于调试和理解)来访问。例如:
let obj = {};
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true
- 原型链:当访问一个对象的属性时,如果该对象本身没有这个属性,JavaScript 会沿着
[[Prototype]]
链向上查找,直到找到该属性或到达原型链的顶端(Object.prototype
,其[[Prototype]]
为null
)。例如:
function Animal() {}
Animal.prototype.speak = function() {
console.log('I am an animal');
};
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
let myDog = new Dog();
myDog.speak(); // 输出 'I am an animal',从 Animal.prototype 中找到 speak 方法
- 类与原型链的关系:ES6 类实际上是在原型链的基础上构建的。类的
prototype
属性会成为其实例的[[Prototype]]
。例如:
class MyClass {
constructor() {}
method() {
console.log('This is a method');
}
}
let instance = new MyClass();
console.log(Object.getPrototypeOf(instance) === MyClass.prototype); // true
在复杂场景中的应用
- 元编程:
- 利用类和原型实现元编程:元编程是指程序可以对自身进行操作的能力。在 JavaScript 中,可以通过修改类的原型来动态地添加或修改方法,实现元编程。例如,实现一个
mixin
模式,将多个对象的方法混入到一个类中:
- 利用类和原型实现元编程:元编程是指程序可以对自身进行操作的能力。在 JavaScript 中,可以通过修改类的原型来动态地添加或修改方法,实现元编程。例如,实现一个
function mixin(target, ...sources) {
sources.forEach(source => {
Object.getOwnPropertyNames(source).forEach(name => {
if (name!== 'constructor' && name!== 'prototype' &&!Object.prototype.hasOwnProperty.call(target, name)) {
Object.defineProperty(target, name, Object.getOwnPropertyDescriptor(source, name));
}
});
});
return target;
}
let mixin1 = {
method1() {
console.log('Method 1 from mixin1');
}
};
let mixin2 = {
method2() {
console.log('Method 2 from mixin2');
}
};
class MyClass {}
mixin(MyClass.prototype, mixin1, mixin2);
let instance = new MyClass();
instance.method1(); // 输出 'Method 1 from mixin1'
instance.method2(); // 输出 'Method 2 from mixin2'
- 高级设计模式:
- 利用原型链实现继承模式:在实现像
组合继承
这样的高级设计模式时,原型链起到了关键作用。组合继承结合了原型链继承和构造函数继承的优点。例如:
- 利用原型链实现继承模式:在实现像
function Shape(color) {
this.color = color;
}
Shape.prototype.getColor = function() {
return this.color;
};
function Rectangle(color, width, height) {
Shape.call(this, color);
this.width = width;
this.height = height;
}
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
Rectangle.prototype.getArea = function() {
return this.width * this.height;
};
let rect = new Rectangle('red', 5, 10);
console.log(rect.getColor()); // 输出'red'
console.log(rect.getArea()); // 输出 50
- **利用类和原型实现单例模式**:单例模式确保一个类只有一个实例。在 JavaScript 中,可以通过类和原型来实现类似功能:
class Singleton {
constructor() {
if (Singleton.instance) {
return Singleton.instance;
}
Singleton.instance = this;
return this;
}
}
let instance1 = new Singleton();
let instance2 = new Singleton();
console.log(instance1 === instance2); // true
通过深入理解 JavaScript 中类和原型的底层机制,可以在复杂场景中灵活运用它们,实现高效、优雅的解决方案。