Object.create继承

用Object.create()来实现继承

首先了解下这个方法

Object.create() 是什么?

Object.create(A, propertiesObject) 用来创建一个新对象 ,并且把它的原型(__proto__)设置为 A

ini 复制代码
const person = {
  greet() {
    console.log(`Hi, I am ${this.name}`);
  }
};

const tom = Object.create(person); // 以 person 作为tom的原型
tom.name = "Tom";

tom.greet(); // Hi, I am Tom

这里:

  • tom.__proto__ === person
  • tom 自己没有 greet,所以会顺着原型链去 person 找。### 第二个参数(可选)

你还可以传入属性描述符:

js 复制代码
const obj = Object.create({}, {
  name: {
    value: "Alice",
    writable: false,   // 不可修改
    enumerable: true,  // 可枚举
    configurable: false // 不可删除
  }
});

console.log(obj.name); // Alice
obj.name = "Bob";      // 修改无效
console.log(obj.name); // Alice

常见用途

  1. 继承

    js 复制代码
    function Animal(name) {
      this.name = name;
    }
    Animal.prototype.sayHi = function() {
      console.log(`I am ${this.name}`);
    };
    
    function Dog(name) {
      Animal.call(this, name);
    }
    
    Dog.prototype = Object.create(Animal.prototype); // 继承
    Dog.prototype.constructor = Dog;
    
    const d = new Dog("Lucky");
    d.sayHi(); // I am Lucky
  2. 创建纯净对象(无原型)

    ini 复制代码
    const dict = Object.create(null);
    dict.apple = "苹果";
    console.log(dict); // { apple: "苹果" }
    console.log(dict.toString); // undefined (因为没有继承 Object.prototype)

对于Object.create()继承中的几个问题

问题一:Dog.prototype = Object.create(Animal.prototype);这里如果写成 Dog.prototype = Animal.prototype可不可以

区别对比

✅ 推荐写法

ini 复制代码
Dog.prototype = Object.create(Animal.prototype);
  • Dog.prototype 是一个全新的对象 ,它的 __proto__ 指向 Animal.prototype
  • DogAnimal 各自的原型对象是独立的
  • 即使你在 Dog.prototype 上新增方法,也不会影响 Animal.prototype

❌ 如果写成

ini 复制代码
Dog.prototype = Animal.prototype;
  • 这表示 Dog.prototypeAnimal.prototype 变成了同一个对象

  • 那么:

    1. Dog.prototype 添加方法时,其实就是在改 Animal.prototype
    2. 所有 Animal 的实例都会意外地拥有 Dog 的方法,破坏继承结构。

举个例子

javascript 复制代码
function Animal() {}
Animal.prototype.sayHi = function() {
  console.log("I am an animal");
};

function Dog() {}
// 错误写法
Dog.prototype = Animal.prototype;

Dog.prototype.bark = function() {
  console.log("Woof!");
};

const a = new Animal();
a.bark(); // ❌ 本来不该有 bark 方法

这里 aAnimal 的实例,结果却能调用 bark,说明原型链被"污染"了。


✅ 正确写法的好处

ini 复制代码
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.bark = function() {
  console.log("Woof!");
};

const a = new Animal();
a.bark(); // ❌ 报错,符合预期
  • Dog 的实例可以继承 Animal 的方法。
  • Animal 的实例不会被"污染"。

总结

  • Dog.prototype = Object.create(Animal.prototype) → 正确、安全的继承方式
  • Dog.prototype = Animal.prototype → 错误,会导致 AnimalDog 共用一个原型对象,互相影响

问题二:Dog.prototype.constructor = Dog;为什么要加上这句话

1. 默认情况下

当你定义一个函数时,JS 会自动给它附带一个原型对象 prototype,并且这个原型对象自带一个 constructor 属性,指向这个函数本身。

javascript 复制代码
function Dog() {}
console.log(Dog.prototype.constructor === Dog); // true

所以默认情况下,constructor 是"指回自己"的。


2. 当你覆盖原型时

在继承时我们常常写:

ini 复制代码
Dog.prototype = Object.create(Animal.prototype);

这会用一个新的对象 替换掉原本的 Dog.prototype

而这个新对象是通过 Object.create(Animal.prototype) 创建的,所以它的 constructor 来自 Animal.prototype.constructor,而不是 Dog

ini 复制代码
console.log(Dog.prototype.constructor === Animal); // true ❌

这就出现了问题:

  • Dog 的实例原型链是对的(能继承 Animal 的方法),
  • Dog.prototype.constructor 却错误地指向了 Animal

3. 手动修复

因此我们需要手动把它修正回来:

ini 复制代码
Dog.prototype.constructor = Dog;

这样做是为了让原型对象的 constructor 指向正确的构造函数。


4. 为什么重要?

虽然在日常开发中 constructor 用得不多,但它能反映某个实例最初是由哪个构造函数创建的

ini 复制代码
const d = new Dog("Lucky");

console.log(d.constructor === Dog);    // true ✅
console.log(d.constructor === Animal); // false

如果不修复,可能导致一些依赖 constructor 的逻辑出错,比如序列化、类型检查等。


✅ 总结

  • 每个函数自带的 prototype 都有一个 constructor,默认指向该函数。
  • 一旦你用 Object.create 替换了 Dog.prototype,它的 constructor 就会错指向 Animal
  • 所以需要 Dog.prototype.constructor = Dog 来修复。
相关推荐
王嘉俊9253 小时前
Flask 入门:轻量级 Python Web 框架的快速上手
开发语言·前端·后端·python·flask·入门
风继续吹..3 小时前
Express.js 入门指南:从零开始构建 Web 应用
前端·javascript·express
一只小风华~3 小时前
命名视图学习笔记
前端·javascript·vue.js·笔记·学习
编程点滴3 小时前
前端项目从 Windows 到 Linux:构建失败的陷阱
linux·前端
小高0073 小时前
🎯GC 不是 “自动的” 吗?为什么还会内存泄漏?深度拆解 V8 回收机制
前端·javascript·面试
RoyLin4 小时前
V8引擎与VM模块
前端·后端·node.js
Keepreal4964 小时前
React受控组件和非受控组件的区别,用法以及常见使用场景
前端·react.js
ITsheng_ge4 小时前
GitHub Pages 部署静态网站流程、常见问题以及解决方案
前端·github·持续部署
web3d5204 小时前
CSS水平垂直居中终极指南:从入门到精通
前端·css