Skip to content

一文搞懂原型链的继承Object.create

1.Object.create()基本介绍

Object.create() 是 JavaScript 中的一个方法,用于创建一个新对象,新对象的原型([[Prototype]])会链接到指定的对象。

注意:是直接将创建出来的新对象的原型指向括号里面的参数(就是一个原型对象),而不是指向括号里面对象的原型对象

具体来说,Object.create() 接受一个参数,即你想要作为新对象的原型的对象。它会创建一个新的对象,使新对象的原型链指向传入的对象。这允许你创建一个继承自其他对象的新对象,而不是使用传统的构造函数或类。

下面是一个示例:

js
const parentObj = {
  greet: function() {
    console.log("Hello!");
  }
};

const childObj = Object.create(parentObj);

childObj.greet(); // 调用继承自 parentObj 的方法

在这个示例中,childObj 是通过 Object.create(parentObj) 创建的。childObj 继承了 parentObj 的属性和方法,因此可以调用 greet 方法。

需要注意的是,使用 Object.create() 并不会执行构造函数,也不会复制原型对象的属性,它只是创建一个新对象,并将新对象的原型链指向你提供的对象。这可以用于实现一些简单的继承关系。

2.实现对象指向函数原型

也就是说,可以实现obj.__proto__ = Fun.prototype;

只要Object.create()里面的参数是Fun.prototype就可以了!

下面是可以实现obj.__proto__ = Fun.prototype;这句话的所有相关方法:

在JavaScript中,obj.__proto__ 是访问对象的原型链的一种方式,而 Fun.prototype 则是构造函数 Fun 的原型对象。通过将 obj.__proto__ 设置为 Fun.prototype,您实际上将 obj 的原型链连接到了 Fun 构造函数的原型对象上。

然而,需要注意的是,__proto__ 虽然在许多浏览器中是支持的,但它不被官方推荐使用,因为它在规范中并没有被标准化。它可能会导致一些兼容性问题,并且不同环境下的行为可能有所不同。

如果您想在现代的 JavaScript 中进行原型链操作,可以使用以下方法:

  1. Object.create():这个方法可以创建一个新对象,使用指定的原型对象作为新对象的原型。

    js
    const obj = Object.create(Fun.prototype);

    注意:这样创建的是一个空对象,但它继承了作为参数传递给 Object.create() 的对象的属性和方法。

  2. Object.setPrototypeOf():这个方法可以设置一个对象的原型为指定的原型对象。

    注意:这样不会创建一个新的对象,相对来说更加灵活 ——> setPrototypeOf是重要的方法

    js
    Object.setPrototypeOf(obj, Fun.prototype);

    Object.getPrototypeOf(obj) = Fun.prototype 等价于Object.setPrototypeOf(obj, Fun.prototype);吗?

    不等价!Object.getPrototypeOf(obj) = Fun.prototype是错误语法!

    1. Object.getPrototypeOf(obj) = Fun.prototype: 这是一个赋值语句,试图将 obj 的原型设置为 Fun.prototype。然而,这样的操作是无效的,因为 Object.getPrototypeOf() 返回的是原型对象,而不能直接赋值给它(返回的是值而不是引用)。这将导致语法错误。

      js
      Object.getPrototypeOf(obj) = Fun.prototype; // 这会导致语法错误
    2. Object.setPrototypeOf(obj, Fun.prototype): 这是一个方法调用,用于将对象 obj 的原型设置为 Fun.prototype。这是正确的做法,可以实现修改对象的原型。

      js
      Object.setPrototypeOf(obj, Fun.prototype);

    所以,正确的做法是使用 Object.setPrototypeOf(obj, Fun.prototype) 来改变对象的原型。Object.getPrototypeOf(obj) 只用于获取对象的原型,不能用于设置原型。

  3. 使用类(ES6中的类和继承):如果您在使用ES6及以上的版本,可以使用类来进行更清晰的原型链操作。

    js
    class Fun {
        // ...
    }
    
    const obj = new Fun();

请记住,在实际应用中,直接操作原型链并不常见,因为它可能会导致不可预料的问题。通常情况下,更推荐使用对象组合、类继承等更清晰和易于理解的方法来处理对象关系。

3.Object.create(null) 和 Object.create({})的区别?

一句话,一个是没有原型链指向的,一个是指向了Object.prototype这个公共的原型!

Object.create(null)Object.create({}) 之间有一个重要的区别,涉及到它们所创建的新对象的原型链以及属性继承。

  1. Object.create(null): **这将创建一个完全空白的对象,它没有任何原型,也就是说,它不会继承任何属性或方法。**这个新创建的对象在原型链上没有父对象,因此它没有内置的属性和方法,也没有继承自其他对象的属性。

    js
    const obj = Object.create(null);
    console.log(obj.toString); // 输出 undefined,因为没有继承任何属性

    使用 Object.create(null) 可以创建一个纯净的对象,适用于不需要继承任何内置属性或方法的场景,但需要注意在这种情况下您将无法使用内置的方法和属性,如 toString

    Object.create(null) 和 new Object()的区别?

    1. Object.create(null): 这将创建一个完全空白的对象,它没有原型链,也就是说,它不会继承任何属性或方法。它是一个纯净的对象,没有任何默认的属性和方法

      js
      const obj = Object.create(null);
      console.log(obj.toString); // 输出 undefined,因为没有继承任何属性
    2. new Object(): 这会创建一个空的普通对象,它的原型链将指向内置的 Object.prototype 对象,因此会继承一些常见的属性和方法,如 toString 等。

      js
      const obj = new Object();
      console.log(obj.toString); // 输出 function toString() { [native code] },继承自 Object.prototype

    总结:

    • Object.create(null) 创建的对象是一个空白对象,没有原型,不继承任何属性和方法。
    • new Object() 创建的对象继承了 Object.prototype 的属性和方法。

    所以,它们不是完全等价的,因为一个是创建一个没有原型链的纯净对象,另一个是创建一个继承了 Object.prototype 属性和方法的对象。

  2. Object.create({}): 这将创建一个新对象,其原型链将指向一个空的普通对象。这意味着新对象继承了空对象的属性和方法,因为它的原型链中存在一个空对象作为父对象。

    js
    const obj = Object.create({});
    console.log(obj.toString); // 输出 function toString() { [native code] },继承自空对象

    使用 Object.create({}) 创建的对象会继承一些常见的内置属性和方法,因为它的原型链指向了一个空的普通对象。

总之,Object.create(null) 创建的对象没有原型,因此不继承任何属性和方法,而 Object.create({}) 创建的对象会继承一个空对象的属性和方法。您可以根据需要选择使用哪种方式创建对象,以适应特定的场景。

4.原型链的尽头是什么?

在 JavaScript 中,原型链的尽头是 null。每个对象都有一个原型(prototype),它是一个链接到其他对象的引用。对象之间的这种链接形成了原型链,通过原型链,JavaScript 可以实现对象之间的继承和属性查找。

原型链的最顶层是 Object.prototype,这是 JavaScript 中所有对象的根原型。Object.prototype 本身没有原型,因此它的原型是 null