javascript - Object.create isn't creating a new object using the module pattern - Stack Overflow

If I create multiple objects using Object.create() on an object literal, I get multiple unique objects

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 badges
Add a ment  | 

3 Answers 3

Reset to default 3

Example 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:

  1. 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.

  2. 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条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信