Javascript: Object Literal reference in own key's function instead of 'this'
Asked Answered
L

5

16

Is it problematic to reference an object literal within a function which is part of that very literal? It seems to work just fine, but I want to make sure there aren't other implications.

Here's an example of what I'm talking about:

instead of:

var obj = {
    key1: "it",
    key2: function(){return this.key1 + " works!"}
};
alert(obj.key2());

using:

var obj = {
    key1: "it",
    key2: function(){return obj.key1 + " works!"}
};
alert(obj.key2());
Leptophyllous answered 22/5, 2012 at 22:30 Comment(0)
G
21

Both can be problematic.

var obj = {
    key1: "it",
    key2: function(){ return this.key1 + " works!" }
};
var func = obj.key2;
alert(func()); // error

When func is not called as a method of obj, this can reference something else (in here: the global object "window").

var obj = {
    key1: "it",
    key2: function(){ return obj.key1 + " works!" }
};
var newref = obj;
obj = { key1: "something else"; };
alert(newref.key2()); // "something else works"

In here we access the object from another reference, though the obj in the function may now point to some other object.

So you will have to choose which case is more likely. If you really want to make it safe, prevent obj from being exchanged:

// ES6 - use `const`:
const obj = {
    key1: "it",
    key2: function(){ return obj.key1 + " works always!" }
};

// ES5: use a closure where the `obj` is stored in a local-scoped variable:
var obj = (function(){
    var local = {
        key1: "it",
        key2: function(){ return local.key1 + " works always!" }
    };
    return local;
})();

or you bind() the function to the object:

var obj = {
    key1: "it",
    key2: function(){ return this.key1 + " works always!" }
}
obj.key2 = obj.key2.bind(obj);
Genseric answered 22/5, 2012 at 22:42 Comment(0)
L
1

There will be a difference in variable scope binding. If you modify obj later, you will modify the return value of key2:

var newobj = obj;
obj = { key1: "new" };
alert(newobj.key2());

Now it alerts "new works!", because even though you are calling key2() on the original object (which is now newobj), the reference to obj.key1 now binds to the value of the new obj instance. Using this prevents this from happening.

Demo: http://jsfiddle.net/m6CU3/

Leatriceleave answered 22/5, 2012 at 22:33 Comment(0)
C
1

If you are not using prototype object, you czn go like that. as all instances of your object will return the value of the obj instance...

Circumjacent answered 22/5, 2012 at 22:35 Comment(0)
H
1

Either or both of those techniques may apply depending on the situation.

The value of this within a function depends on how the function was called. If you call a function as property of an object like this:

obj.key2();
//or
obj["key2"]();

Then this will be that object. Whether the object was created via an object literal or some other means is not relevant.

But you can use .call() or .apply() to call a function and explicitly set this to some other object.

Consider also:

var obj = {
    key1: "it",
    key2: function(){return this.key1 + " works!"}
};
alert(obj.key2()); // alerts "it works!"

var func = obj.key2;
alert(func())​;     // alerts "undefined works!"

I'm setting up func to reference the same function as obj.key2, but calling it as func() does not set this to obj.

For more information have a look at what MDN has to say about this.

Hippodrome answered 22/5, 2012 at 22:42 Comment(0)
E
0

I don't think there are any implications off the top of my head. Just make sure you don't accidentally do this at any point:

var obj = {
    key1: "it",
    key2: key1 + " works!"
}

As that will cause an error. Other than that, you should be good to go!

Eruct answered 22/5, 2012 at 22:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.