2023前端面试:又来问原型继承的工作原理了

86 阅读2分钟

前沿知识

对于使用过基于类的语言 (如 Java 或 C++) 的开发者们来说,JavaScript 实在是有些令人困惑 —— JavaScript 是动态的,本身不提供一个 class 的实现。即便是在 ES2015/ES6 中引入了 class 关键字,但那也只是语法糖,JavaScript 仍然是基于原型的。

原型继承的工作原理

当谈到继承时,JavaScript 只有一种结构:对象。

每个实例对象(object)都有一个 私有属性(称之为 __ proto__)指向它的构造函数的原型对象( prototype )。该原型对象也有一个自己的原型对象,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。

几乎所有 JavaScript 中的对象都是位于原型链顶端的 [Object]

原型继承的核心就是通过这个原型链来实现的。当我们创建一个新对象时,可以指定该对象的原型,这个原型可以是任何一个已存在的对象,也可以是 null。新对象从其原型对象继承了所有的属性和方法,如果在新对象上没有定义该属性或方法,JavaScript 引擎就会通过原型链查找。

例如,我们可以使用 Object.create() 方法来创建一个新对象,并指定其原型:

javascript

const parent = {
  sayHello() {
    console.log('Hello!');
  }
};

const child = Object.create(parent);

在这个例子中,child 对象的原型被设置为 parent 对象,因此它从 parent 继承了 sayHello() 方法。我们可以通过以下方式调用该方法:

child.sayHello(); // 输出 "Hello!"

控制台显示:

image.png

备注: 遵循 ECMAScript 标准,child.[[Prototype]] 符号是用于指向 child 的原型。从 ECMAScript 6 开始,[[Prototype]] 可以通过 [Object.getPrototypeOf()]和 [Object.setPrototypeOf()] 访问器来访问。这个等同于 JavaScript 的非标准但许多浏览器实现的属性 __proto__

关于创建原型对象,可以看下:juejin.cn/post/720841…