-1

I have stumbled upon something that bugs me. I had to copy one object so I have written a helper function for that task.

function deepCopy2(target, obj) {

    for (var prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            if (typeof obj[prop] !== 'object') {
                target.prop = obj[prop];
            } else {
                var embedded = {};
                deepCopy2(embedded, obj[prop]);
                target.prop = embedded;
            }
        }
    }
    return target;
}

For some reason this doesn't work. So I have just changed .(dot) assignment into [ ] as is shown below, and it works.

function deepCopy1(target, obj) {

    for (var prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            if (typeof obj[prop] !== 'object') {
                target[prop] = obj[prop]; // changed here
            } else {
                var embedded = {};
                deepCopy1(embedded, obj[prop]);
                target[prop] = embedded; // changed here
            }
        }
    }
    return target;
}

If I do the following.

var obj = {
    name: 'john',
    getName: function() { return true; },
    inner: { age: 23 }
};

var newObj1 = deepCopy1({}, obj);
var newObj2 = deepCopy2({}, obj);

console.log(obj);
console.log(newObj1);
console.log(newObj2);

I get

{name: "john", getName: ƒ, inner: {…}}
{name: "john", getName: ƒ, inner: {…}}
{prop: {…}}

Meaning that the first function failed and instead of copying properties one by one, It just created property called prop.

I have found this Valid property names, property assignment and access in JavaScript as well as this JavaScript property access: dot notation vs. brackets? and searched also on MDN but nothing leads to the answer.

I have also looked whether prop name can be freely used and didn't find any restrictions.

Can anyone explain to me why the first approach doesn't work while the second does?

Matus Dubrava
  • 13,637
  • 2
  • 38
  • 54

2 Answers2

1
target.prop
// same as
target['prop']

does not use prop as variable, but works as hardcoded property with the name prop. The variable is not used here.

target[prop]

takes the variable prop and uses the value of it as key.

Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

As you already know, there is two ways to retrieve an object property:

object[prop]

/* OR */

object.prop

You may ask, why?

Now there is a difference among the two.

1 . object.prop

In this approach, the prop is used as a property name.

Meaning, this way of retrieving says that you already know that the property prop exist in that object.

var object = {
        dummy: 1,
        prop: 2
    }

console.log(object.prop);  // Outputs 2

When the property is absent:

var object = {
        dummy: 1
    }

console.log(object.prop);  // Outputs undefined

Because there is no such property (that is why it is undefined).

2. object[prop]

In this approach, you are using the prop as an variable instead of a property name.

Meaning, the prop can be any value and this value can or cannot be a defined property in an object.

var prop = 'prop';
var object = {
        dummy: 1,
        prop: 2
    }

console.log(object[prop]);  // Outputs 2

Same when it is absent:

var prop = 'prop';
var object = {
        dummy: 1
    }

console.log(object[prop]);  // Outputs undefined

Because of the same reason.

However, if you add that property to that object later:

var prop = 'prop';
var object = {
        dummy: 1
    }

console.log(object[prop]);  // Outputs undefined

object.prop = 2;
console.log(object[prop]);  // Outputs 2

prop = 'abc';
console.log(object[prop]);  // Outputs undefined

object['abc'] = 3;
console.log(object[prop]);  // Outputs 3
yqlim
  • 6,898
  • 3
  • 19
  • 43