0

I am trying this example from Douglas Crokford video, and as per my knowledge, changing the new object should not change the old object.

   var oldObject = {
        firstMethod:function(){
            console.log("This is first method");
        },
        secondMethod:function(){
            console.log("This is second method");
        }
    }

    var newObject = Object(oldObject);

    newObject.thirdMethod=function(){
        console.log("thirdMethod");
    }

    newObject.firstMethod=function(){
        console.log("I am not first method");
    }

    newObject.firstMethod();
    oldObject.firstMethod();

Output:

I am not first method
I am not first method

But I expected,

I am not first method
This is first method

Please let me know where I am wrong.

jforjs
  • 465
  • 1
  • 4
  • 11

4 Answers4

1

If you call the Object constructor as a function, it performs type conversion (in this case nothing since the argument is already an object). (If you were to call it as a constructor and pass it an object, as you do there, then it just returns that object).

newObject isn't a new object, it is the same object. Any modifications to newObject are therefore also modifications to oldObject.

Possibly you want:

var newObject = {};
newObject.prototype = oldObject;

Instead of the Object() call.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
1

TL;DR: that's (most probably) a typo in your code: it should have been written like this:

var newObject = Object.create(oldObject);

Now for explanations. This line ...

var newObject = Object(oldObject);

... does not create a new object: instead newObject variable becomes storage of the reference to the same object oldObject refers to. Here's what standard says about it:

15.2.1.1: When the Object function is called with no arguments or with one argument value, the following steps are taken:

  1. If value is null, undefined or not supplied, create and return a new Object object exactly as if the standard built-in Object constructor had been called with the same arguments
  2. Return ToObject(value).

9.9: The abstract operation ToObject converts its argument to a value of type Object according to Table 14: [ ... ]

Object: The result is the input argument (no conversion).


What you probably wanted to do is use oldObject as a prototype of the new one instead. The most 'direct' way of doing it, when you already have an object, is working with __proto__ property:

var newObject = {
  firstMethod: function() { console.log("I am not the firstMethod"); },
  thirdMethod: function() { console.log("thirdMethod"); } 
};
newObject.__proto__ = oldObject;

This feature is quite ubiquitous these days (apart from IE10-, basically all modern browsers support it). It's not a part of ES5 standard, but it probably will be of ES6.

But I guess Crockford actually meant it this way:

var newObject = Object.create(oldObject);

... as this, quoting the standard yet again, 'creates a new object with a specified prototype'.

raina77ow
  • 103,633
  • 15
  • 192
  • 229
0

Yep, when you try to copy an object in javascript it simply passes it as a reference to the original, so any changes to new ones will affect the original. If you are using jQuery simply do this:

var newObject = $.extend({},oldObject);

That should solve your issue. Take a look at this for a more in-depth answer: How do I correctly clone a JavaScript object?

EDIT

Also, from the above thread a non jQuery solution:

Object.prototype.clone = function() {
  if(this.cloneNode) return this.cloneNode(true);
  var copy = this instanceof Array ? [] : {};
  for(var attr in this) {
    if(typeof this[attr] == "function" || this[attr]==null || !this[attr].clone)
      copy[attr] = this[attr];
    else if(this[attr]==this) copy[attr] = copy;
    else copy[attr] = this[attr].clone();
  }
  return copy;
}
Community
  • 1
  • 1
Villarrealized
  • 867
  • 1
  • 6
  • 13
0

Javascript pass object as "reference", so

var newObject = oldObject; // the old Object() just make a type cast, not necessary here

Just make newObject/oldObject reference the same object, and

newObject.firstMethod = 

will just overwrite the firstMethod of oldObject too.

So to make newObject a new object, you need to do this:

var newObject = {}; //a new object
for(var k in oldObject)
{
     newObject[k]= oldObject[k]; //copy old attrs
}

And then you can overwrite the methods

Andrew
  • 5,290
  • 1
  • 19
  • 22