了解 Crockford 的 Object.create shim

IT技术 javascript prototype object-create
2021-02-18 19:54:42

我一直在阅读 Crockford shim 以防止覆盖原型,并理解它有时不是最终/全部解决方案。我也明白ES5 Shim可能是一个可行的替代方案。我还阅读了这篇文章,它提供了一个更强大、更安全的替代方案

不过,我想知道他的Object.createshim 在“说什么”然后“做什么”。有人可以告诉我我的解释评论是否正确吗?

if (typeof Object.create === 'undefined') { 
//If the browser doesn't support Object.create

  Object.create = function (o) {
  //Object.create equals an anonymous function that accepts one parameter, 'o'.

    function F() {};
    //Create a new function called 'F' which is just an empty object.

    F.prototype = o;
    //the prototype of the 'F' function should point to the
    //parameter of the anonymous function.

    return new F();
    //create a new constructor function based off of the 'F' function.
  };
}

//Then, based off of the 'Lost' example in the Crockford book...

var another_stooge = Object.create(stooge);

//'another_stooge' prototypes off of 'stooge' using new school Object.create.
//But if the browser doesn't support Object.create,
//'another_stooge' prototypes off of 'stooge' using the old school method.

这样,当我们将东西增加到“another_stooge”时,“stooge”对象的原型就不会被覆盖。无需使用“构造函数”重置“stooge”原型。

提前致谢,

-k

5个回答
if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}
var oldObject={prop:'Property_one' }; // An object
var newObject = Object.create(oldObject); // Another object

在上面的示例中,我们newObject使用create方法创建了一个新对象,方法是Object我们Object之前在(Crockford 的)示例中添加到对象中的对象的成员函数所以基本上它的作用是,该create方法声明一个函数F,一个空对象every function is a first class object in javascript,然后我们继承了的原型o(在这种情况下o也是一个oldObject作为create方法参数传递的对象),最后我们返回了新的对象(F 的一个实例)使用return new F();到变量newObject,所以现在newObject是一个继承了oldObject. 现在如果你写console.log(newObject.prop);那么它会输出Property_one因为我们的newObject对象已经继承了oldObject这就是为什么我们得到了propas的值Property_one这被称为原型继承。

您必须传递一个对象作为create方法的参数

它所做的只是创建一个新的对象构造函数,即 F,然后将传递的对象分配给构造函数原型属性,以便使用 F 构造函数创建的新对象继承这些方法。

然后使用构造函数返回一个新初始化的对象(new F() => F.prototype)

但是 crockford 未能正确地重新分配构造函数,因为通常新的对象构造函数应该与其继承的对象构造函数相同。

嗨,吉尔斯克。感谢您的回复!那么当使用这个时,是否意味着需要重置构造函数的原型?类似于:stooge.prototype.constructor = stooge; 再次感谢!
2021-05-08 19:54:42

关于你的评论:

>   //Object.create equals an anonymous function that accepts one parameter, 'o'.

最好说一个函数被分配给 的create属性Object所有函数都可以被认为是匿名的,只是有些函数被分配给命名的属性或变量,有些则不是。

> //Create a new function called 'F' which is just an empty object.

声明一个函数。是的,它也是一个对象。

>     F.prototype = o;
>     //the prototype of the 'F' function should point to the
>     //parameter of the anonymous function.

o分配给的引用F.prototype写起来短一些。

>     //create a new constructor function based off of the 'F' function.

不,应该是“返回 F 的实例”。所以返回的对象有一个内部[[Prototype]]引用传递给函数的对象。混乱的部分是必须创建一个无用的 F 函数来执行这个技巧,并且返回的对象的构造函数将没有有用的值,因为它引用了空的F.

并不是说构造函数属性通常非常可靠或特别有用。

这样,当我们将东西增加到“another_stooge”时,“stooge”对象的原型就不会被覆盖。无需使用“构造函数”重置“stooge”原型。

这是一个奇怪的说法。*another_stooge*stooge因为它是私有的[[Prototype]],所以它不是继承自stooge.prototype而是自stooge.[[Prototype]]

如果你想another_stooge继承自stooge.prototype,使用Object.create(stooge.prototype)Object.create(new stooge()),前者可能更合适。

我希望一切都说得通。

嗨,RobG。感谢您的回复!我必须重新阅读才能完全理解语法,但我当然比一个小时前知道的更多。再次感谢!
2021-04-17 19:54:42

这里有两个技巧:

  1. F 不是一个简单的函数,它是一个构造函数。
  2. “F.prototype”只是一个属性,此时它与继承无关。真正的技巧是,当我们使用“new F()”时,“new”会创建一个新对象,调用构造函数(此处不执行任何操作)并将新对象的内部“prototype”字段设置为“ F.prototype”,因此返回的对象将从“o”继承。

所以我认为:

  • F 是一个构造函数
  • F 不是从 o 继承的
  • “new F”(这是返回的对象)是从 o 继承的

我想将内部函数命名为Object而不是F使生成的对象看起来更接近Object.create()将创建的对象

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function Object() {}
        Object.prototype = o;
        return new Object();
    };
}