15

I have an object in javascript:

admins: {
    articles: {
        path: '/admins/articles',
        template: '/views/admins/articles.html',
        link: function() {
            return path;  // !!! how to reference the 'path'?
        }
    }
}

I have a lot of objects like this, and each of them has a path field and a link function. I want to use the field path in link, but I can't just use path.

What should I do?

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
Freewind
  • 193,756
  • 157
  • 432
  • 708

5 Answers5

14

You can use this to reference the object. Standard object.method() "dot" syntax will set this to object within method:

var someObj = {
    admins: {
        articles: {
            path: '/admins/articles',
            template: '/views/admins/articles.html',
            link: function() {
                return this.path; // !!! how to reference the 'path'?
            }
        }
    }
};

var returnedPath = someObj.admins.articles.link();

Demo: http://jsfiddle.net/2Pt7n/

(There are other ways to call a function such that this will not be set to the appropriate object, but I hope they don't apply here - you don't really say how you're using the objects or calling the function, but if not in the way I showed then please update your question and I'll update my answer accordingly.)

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
  • This is a slightly less verbose approach then what I posted and might be better. But as nnnnnn said, there are many ways in JavaScript to change the "this" scope which will break the link function. If those don't apply to you, this may be the better way because it is shorter and doesn't require knowledge of any parent objects. – Jason L. Jul 20 '12 at 03:28
5

I'll just point out that you don't want to use ES6 fat arrow here, because there will be no this pointer in that case:

var someObj = {
    admins: {
        articles: {
            path: '/admins/articles',
            template: '/views/admins/articles.html',
            link: () => {
                return this.path; // 'this' is undefined
            }
        }
    }
};

someObj.admins.articles.link() === undefined

Jeff Lowery
  • 2,492
  • 2
  • 32
  • 40
2

What you are showing is not JSON. It is a Javascript object, which is different than JSON. JSON is a strictly defined data serialization format that is a subset of Javascript object literals.

Javascript provides no syntax for referencing peer properties in an object literal, as you want to do. Naming them is one idea, but it won't help, because the name won't exist while the literal is being defined, so the name is not available for you to use in the literal itself.

Also, note that the syntax you define makes the object lop-sided: you can access path as obj.admins.articles.path, but link is a function you would have to invoke: obj.admins.articles.link().

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
2

I won't talk about how this is not JSON (others covered it well).

You can do this to get path:

return admins.articles.path;

Here's a fiddle to show it working: http://jsfiddle.net/UwbLt/

Alexander Gonchiy
  • 916
  • 11
  • 17
Jason L.
  • 2,464
  • 1
  • 23
  • 41
1

I'm reading the answers and even understanding the point of some users (that JSON should be used just for data) and agreeing that this is correct, I just created a proof of concept example. Take a look.

// just a regular object
var obj = {
    a: "aaa",
    b: "bbb",
    c: function() {
        return this.a;
    }
};

console.log( obj.c() ); // prints "aaa"

// isn't it json just because it has a function? ExtJS will treat it like JSON, but jQuery not
var json = "{" +
    "\"a\": \"aaa\", " +
    "\"b\": \"bbb\", " +
    "\"c\": function() {" +
    "    return this.a;" +
    "}" +
"}";

// ok, the "json" above
console.log( json );

//var jsonObj = $.parseJSON( json ); // does not work
//var jsonObj = eval( json ); // does not work too
var jsonObj = Ext.decode( json ); // it works! shortcut for Ext.JSON.decode

console.log( jsonObj.c() );       // prints "aaa"

It is almost the same that nnnnnn posted, but I think I would post it too, just to complement the answers. jsFiddle: http://jsfiddle.net/davidbuzatto/rhKAM/

So I think, even contradicting the definition of JSON, that JSON maybe can have (or should have?) the same characteristics of a object created using the regular object initializer sintax, since its name is JavaScript Object Notation, not "Lightweight" Object Notation. I know, I know, a deserializer won't be able to deserialize a function depending on the target language, but why ExtJS supports this "behavior"? A good discussion can be found here: Is it valid to define functions in JSON results?

Just to clarify. I don't use (and I won't use too) functions inside my JSONs.

Community
  • 1
  • 1
davidbuzatto
  • 9,207
  • 1
  • 43
  • 50
  • JSON was designed to be programming language independent, which is why the data types permitted in JSON are [explicitly defined](http://json.org) and do not include functions. But note that even when you know you're only going to be using JavaScript at both ends, capturing the body of a function as text is not the same as capturing a function object, because functions don't exist in isolation, they have access to the scope where they're defined. – nnnnnn Feb 03 '18 at 07:00