33. Object.create 是怎么实现继承的? 副本.md 来源:https://my.feishu.cn/file/XB5wb9fyWogzAMxzvOJcI4qgnfc 采集状态:已完成正文采集;原文件源码视图逐行采集,行号 1 至 83 连续,滚动到底。 ### 1. 核心概念 (Core Concept) `Object.create()` 是 JavaScript 中用于创建一个新对象的方法。这个新对象的原型是调用 `Object.create()` 时传入的第一个参数。通过指定一个现有对象作为新对象的原型,`Object.create()` 实现了一种基于原型链的“继承”机制,即原型式继承(Prototypal Inheritance)。 ### 2. 为什么需要它? (The "Why") * **更纯粹的原型继承方式:** 它提供了一种直接设置新对象的原型,而不是通过构造函数和 `new` 操作符来实现继承的方式。这比传统的构造函数继承更加灵活和直接地表达了“使一个对象成为另一个对象的原型”的关系。 * **创建没有原型对象:** 可以通过传入 `null` 作为原型创建完全独立、没有继承任何属性(包括 `Object.prototype` 上的方法如 `toString`)的对象,这在某些特定场景(如字典、哈希表)中非常有用。 * **隔离父对象的影响:** 通过创建一个中间空对象作为原型,可以避免直接修改父对象或构造函数的 `prototype` 属性,从而更好地实现继承并管理属性的查找链路。 ### 3. API 与用法 (API & Usage) `Object.create()` 方法创建一个新对象,使用现有的对象来提供新创建的对象的 `__proto__`。 **语法:** ```javascript Object.create(proto, propertiesObject) ``` **参数:** * `proto`: 新创建对象的原型对象。可以是一个对象或 `null`。 * `propertiesObject` (可选): 一个对象,其属性是新创建对象拥有的可枚举属性的描述符。这些属性会添加到新对象自身上。 **返回值:** 一个新对象,其原型是指定的 `proto`。 **经典用法 - 实现原型式继承:** 这种方式常用于模拟类继承中子类继承父类原型上的方法和属性。 ```javascript // 父对象或者说用作原型的对象 const animal = { type: 'Animal', sayHello: function() { console.log(`Hello from a ${this.type}`); } }; // 子对象,通过 Object.create 设置其原型为 animal const dog = Object.create(animal); // 设置子对象自身的属性 dog.type = 'Dog'; dog.name = 'Buddy'; console.log(dog.type); // 输出: Dog (自身的属性屏蔽了原型上的属性) dog.sayHello(); // 输出: Hello from a Dog (调用原型上的方法,this指向调用者 dog) console.log(dog.__proto__ === animal); // 输出: true (dog 的原型是 animal) ``` **经典用法 - 创建没有原型链的对象:** ```javascript const pureObject = Object.create(null); pureObject.name = 'No Prototype'; console.log(pureObject.name); // 输出: No Prototype // console.log(pureObject.toString()); // Uncaught TypeError: pureObject.toString is not a function console.log(pureObject.__proto__); // 输出: undefined (没有原型) ``` ### 4. 关键注意事项 (Key Considerations) 1. **`this` 的指向:** 通过 `Object.create` 创建的对象调用其原型上的方法时,方法内部的 `this` 仍指向调用该方法的对象(即新创建的实例对象),这与构造函数继承的行为一致。 2. **属性查找:** 当访问新对象的属性时,如果对象自身没有该属性,JavaScript 会沿着原型链向上查找,直到找到匹配的属性或到达原型链的顶端 (`null`)。 3. **与构造函数结合使用:** `Object.create()` 经常与构造函数模式结合使用,以更优雅地实现类的继承。通常是将子类构造函数的 `prototype` 设置为 `Object.create(Parent.prototype)`,然后在子类原型上添加子类特有的方法。 4. **`propertiesObject` 参数:** 第二个参数的使用相对较少,用于在创建时直接定义对象的自有属性及其描述符(如 `writable`, `enumerable`, `configurable`, `value`, `get`, `set`)。 ### 5. 参考资料 (References) * **MDN Web Docs: Object.create()** * [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create) * [https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create) (中文) * **JavaScript 权威指南(第 7 版) - 原型继承** * (此为书籍,无直接在线链接,但描述性地指出了 `Object.create` 在原型继承中的地位) * **ECMAScript® 2024 Language Specification** * [https://tc39.es/ecma262/multipage/ordinary-and-exotic-objects-semantics.html#sec-object.create](https://tc39.es/ecma262/multipage/ordinary-and-exotic-objects-semantics.html#sec-object.create) 原文链接与附件索引 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create https://tc39.es/ecma262/multipage/ordinary-and-exotic-objects-semantics.html#sec-object.create https://tc39.es/ecma262/multipage/ordinary-and-exotic-objects-semantics.html#sec-object.create