If I create multiple objects using Object.create() on an object literal, I get multiple unique objects that don't share property values. However, when I use Object.create() on an object returned from a module, it looks like they share the same reference? Why is that?
#1 Module:
var objModule = (function () {
var name = "module 1";
var setName = function( strName ) {
name = strName;
};
var getName = function() {
return name;
};
return {
setName: setName,
getName: getName
};
}());
var objModule2 = Object.create(objModule);
objModule2.setName("module 2");
console.log(objModule.getName()); // WRONG prints "module 2"
console.log(objModule2.getName()); // prints "module 2"
#2 Literal:
var objLiteral = {
name : "literal 1"
};
var objLiteral2 = Object.create(objLiteral);
objLiteral2.name = "literal 2";
console.log(objLiteral.name); // prints "literal 1"
console.log(objLiteral2.name); // prints "literal 2"
EDIT
#3 Module "Constructor":
var module = function () {
var name = "module 1";
var setName = function( strName ) {
name = strName;
};
var getName = function() {
return name;
};
return {
setName: setName,
getName: getName
};
};
var objModule1 = module();
var objModule2 = module();
objModule2.setName("module 2");
console.log(objModule1.getName()); // prints "module 1"
console.log(objModule2.getName()); // prints "module 2"
EDIT
If I use the module like a constructor (as suggested by @Matt Browne) and create 2 objects, the result is like using an object literal. What I'd like to understand is why does module example #1 behave differently than module example #3?
EDIT 2
As @ben336 explained, the code:
var objModule2 = Object.create(objModule);
will set the objModule2's prototype to objModule. That doesn't happen in example #3, so those two objects don't share the same closure property.
If I create multiple objects using Object.create() on an object literal, I get multiple unique objects that don't share property values. However, when I use Object.create() on an object returned from a module, it looks like they share the same reference? Why is that?
#1 Module:
var objModule = (function () {
var name = "module 1";
var setName = function( strName ) {
name = strName;
};
var getName = function() {
return name;
};
return {
setName: setName,
getName: getName
};
}());
var objModule2 = Object.create(objModule);
objModule2.setName("module 2");
console.log(objModule.getName()); // WRONG prints "module 2"
console.log(objModule2.getName()); // prints "module 2"
#2 Literal:
var objLiteral = {
name : "literal 1"
};
var objLiteral2 = Object.create(objLiteral);
objLiteral2.name = "literal 2";
console.log(objLiteral.name); // prints "literal 1"
console.log(objLiteral2.name); // prints "literal 2"
EDIT
#3 Module "Constructor":
var module = function () {
var name = "module 1";
var setName = function( strName ) {
name = strName;
};
var getName = function() {
return name;
};
return {
setName: setName,
getName: getName
};
};
var objModule1 = module();
var objModule2 = module();
objModule2.setName("module 2");
console.log(objModule1.getName()); // prints "module 1"
console.log(objModule2.getName()); // prints "module 2"
EDIT
If I use the module like a constructor (as suggested by @Matt Browne) and create 2 objects, the result is like using an object literal. What I'd like to understand is why does module example #1 behave differently than module example #3?
EDIT 2
As @ben336 explained, the code:
var objModule2 = Object.create(objModule);
will set the objModule2's prototype to objModule. That doesn't happen in example #3, so those two objects don't share the same closure property.
Share Improve this question edited Jun 1, 2013 at 15:29 Rick Jolly asked Apr 21, 2013 at 2:06 Rick JollyRick Jolly 3,0192 gold badges26 silver badges31 bronze badges3 Answers
Reset to default 3Example 1
The first argument of Object.create
specifies the prototype object for the new object being created. Since in your first example you're setting your existing object to be the prototype of your new object, when you call the functions they're modifying the variable you've stored in a closure, which is then accessed by both your existing object and the new one.
The 2 key things to understand here are:
This code
var objModule = function () { var name = "module 1"; var setName = function( strName ) { name = strName; }; var getName = function() { return name; }; return { setName: setName, getName: getName }; }();
creates a closure with the functions getName and setName holding access to the
name
variable.those functions are properties of objModule, and when you call
Object.create
you set objModule to be the prototype of objModule2, and it gains access to those functions as well.
Since the 2 objects share those functions, and they have access to the closure created by the module rather than storing the name property locally on either object, when you call the set function with one object, it will update the closure and thus update both objects.
Example 2
In the second example you're also setting the object to be the prototype of the new object, but you're declaring a property on the local object which overrides the property on the prototype.
objModule2.setName
refers to the same function as objModule.setName
, but with a different this
. (Object.create
doesn't copy anything)
Calling it will set the same local variable.
objLiteral2.name = "literal 2"
creates a new property on objLiteral2
, which shadows the inherited objLiteral.name
.
I think what you're going for here would be better acplished by removing the parentheses ()
at the end of the objModule
function, and renaming it to something that makes it clear it's a constructor, i.e. do this instead:
var makeObjModule = function() {
var name = "module 1";
var setName = function( strName ) {
name = strName;
};
var getName = function() {
return name;
};
return {
setName: setName,
getName: getName
};
}; //removed parentheses here
(Personally I'd use the function objModule()
syntax too while I was at it, but that's a separate point and a matter of personal preference.)
Then you can create your instances:
var objModule = makeObjModule();
var objModule2 = makeObjModule();
The Object.create
approach is of course a valid way of going about this as well; for more details on making that work, see @ben336's answer.
Personally I find Object.create
to be more useful when doing inheritance than when doing simple construction like this. (Some people also prefer it to using the new
keyword when using prototypal inheritance, but since you're using the module pattern I think it's easier to just use a "maker"/constructor function as I showed above.)
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745173773a4615085.html
评论列表(0条)