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 来修复。
相关推荐
云水一下4 分钟前
Vue.js从零到精通系列(七):高级特性实战——Teleport、异步组件、自定义指令与TypeScript深度结合
前端·vue.js·typescript
qq4356947016 分钟前
Vue05
前端·vue.js
qq_422152579 分钟前
PDF 解密工具怎么选?2026 年文档密码移除方案与注意事项
java·前端·pdf
YHHLAI12 分钟前
前端工程化调用 AI 多模态生图模型:Qwen Image Demo 实战
前端·人工智能
To_OC26 分钟前
我一直以为 Ajax 是个黑盒,直到我写了这 50 行代码
前端·后端·全栈
用户0595401744630 分钟前
RAG 记忆层踩坑实录:用户偏好凭空消失,我排查了 4 小时,最后用 LangChain + Chroma 搭了套自动化回归测试
前端·css
程序猿阿伟37 分钟前
《Chrome隔离机制的维度落地指南》
前端·chrome
用户0543243297038 分钟前
AI 生成的代码怎么在前端安全预览 + 一键运行:sandbox iframe 实战 🔒
前端
ALianBlank39 分钟前
一个 Unity 框架能做多少事?86 个模块 + 21 个小游戏平台
前端·后端·游戏开发
To_OC43 分钟前
搞懂二叉树递归遍历,我居然是从爬楼梯开始的
前端·javascript·数据结构