Understanding Crockford's Object.create shim

女生的网名这么多〃 提交于 2020-01-07 03:55:10

问题


I've been reading up on the Crockford shim for preventing the overwriting of prototypes, and understand that it's not the end-all/be-all solution at times. I also understand that ES5 Shim may be a viable alternative to this. I also read this post which provides a more robust, secure alternative.

Still, I'd like to know what his Object.create shim is "saying" and then "doing." Can someone please tell me if my explanation comments are right?

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.

This way, the prototype of the 'stooge' object can't be overwritten when we augment stuff to 'another_stooge'. No need to reset the 'stooge' prototype using 'constructor'.

Thanks in advance,

-k


回答1:


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

In the above example we've created a new object newObject using create method which is a member function of Object object that we've added in the Object object earlier in our (Crockford's) example. So basically what it does is that, the create method declares a function F, an empty object every function is a first class object in javascript and then we've inherited the prototype of o (in that case o is also an object oldObject passed as the parameter of create method) and finally we've returned the new object (an instance of F) using return new F(); to the variable newObject, so now newObject is an object that inherited the oldObject. Now if you write console.log(newObject.prop); then it'll output Property_one because our newObject object has inherited the oldObject and that's why we've got the value of prop as Property_one. this is known as prototypical inheritance.

You must pass an object as the parameter of create method




回答2:


All it does is create a new object constructor, which is F, it then assign the passed object to the constructor prototype property so that new object created with the F constructor inherit those methods.

It then use the constructor to return an newly initialize object (new F() => F.prototype)

But the crockford one fail to reassign the constructor properly as normally the new object constructor should be the same as the object constructor it inherits from.




回答3:


On your comments:

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

Better to say that a function is assigned to the create property of Object. All functions can be considered anonymous, just that some are assigned to named properties or variables, others aren't.

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

Declare a function. Yes, it's an object too.

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

A reference to o is assigned to F.prototype is a bit shorter to write.

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

No, should be "Return an instance of F". So the returned object has an internal [[Prototype]] that references the object passed to the function. The messy part is that a useless F function had to be created to perform the trick, and the returned object's constructor will not have a useful value as it references the empty F.

Not that the constructor property is very reliable or particularly useful normally anyway.

This way, the prototype of the 'stooge' object can't be overwritten when we augment stuff to 'another_stooge'. No need to reset the 'stooge' prototype using 'constructor'.

That's a strange statement. *another_stooge* has stooge as it's private [[Prototype]], it does not inherit from stooge.prototype but from stooge.[[Prototype]].

If you want another_stooge to inherit from stooge.prototype, use Object.create(stooge.prototype) or Object.create(new stooge()), the former is probably more suitable.

I hope that all makes sense.




回答4:


There are two tricks here:

  1. F is not a simple function, it is a constructor.
  2. "F.prototype" is just a property, it does nothing with inheritance in this moment. The real trick is that when we use "new F()", the "new" creates a new object, calls the constructor (which does not do anything here) AND sets the new object's internal "prototype" field with the value of "F.prototype", so the returned object will inherit from "o".

So I think, that:

  • F is a constructor
  • F is not inherit from o
  • "new F" (which is the returned object) is inherit from o



回答5:


I guess naming the internal function as Object instead of F makes the resulting object look closer to what Object.create() would create.

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


来源:https://stackoverflow.com/questions/33914138/a-temporary-constructor-new-f

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!