最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Understanding Crockford's Object.create shim - Stack Overflow

programmeradmin4浏览0评论

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

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

Share Improve this question edited May 23, 2017 at 12:25 CommunityBot 11 silver badge asked Apr 13, 2012 at 12:44 kaidezkaidez 6799 silver badges28 bronze badges
Add a comment  | 

5 Answers 5

Reset to default 15
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

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.

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.

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

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();
    };
}
发布评论

评论列表(0)

  1. 暂无评论