问题
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:
- F is not a simple function, it is a constructor.
- "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/10141086/understanding-crockfords-object-create-shim