Javascript Object Literal Notation - Creating mixins (sort of)
For lack of a better title... Is it possible to do something like this in JSON?
var obj = {
a : 'a constant',
b : a + ' and b constant'
}
Update: Doesn't work - this.a returns undefined
I know this will work but it looks rather ugly and convoluted:
var obj = {
a : 'a constant',
b : (function(){ return this.a + ' and b constant'; })()
}
And here's what I have currently:
var obj = {
a : 'a constant',
b : 'a constant and b constant'
}
I know of the other ways that some have commented upon and I sincerely thank them for responding. However, they don't look simple or elegant. The only issue I have with my current implementation is that if value of 'a' ever gets updated, search-n-开发者_Go百科replace has to done in many places (I say many because there are more properties that derive from 'a') instead of one.
In JSON, no. http://json.org/
Did you mean in javascript?
JSON is a data format. It has no concept of functions, just like any other data format (HTML, XML, plain text).
The only purpose this would seem to serve is data compression. Why don't you just compress the data using one of the many standard implementations out there instead?
If you expect your data to have massive redundancies of a sort that would not be efficiently compressed by a normal compression scheme, then you could do something like you're talking about here, e.g.
var obj = {
a : 'a constant',
b : '[fld=a] and b constant'
}
and your code at either end would have to implement and parse this. That is, it would search for [fld=x]
in each member and substitute with the value of member x
. But it's still just a custom data compression scheme. It has nothing to do with JSON.
edit
Javascript Objects
and JSON
are entirely different (albeit related) things. A Javascript object is any entity in Javascript. JSON is a data format that is meant to represent the programmatic object in a text-based notation, specifically for the purpose of exchange with other programmatic entities across a wire (or when the internal format is otherwise not portable).
If you are just asking if a Javascript object can contain a function that refers to another one of it's members, then sure, you already answered your own question!
You don't need a self-executing function though, that just creates work, and it would also end up not reflecting any changes made to A in the future. Just do a regular function:
b : function() { return this.a + ' and b constant'; };
or more likely, just create a "method" and leave your fields alone:
var obj = {
a : 'a constant',
b : 'b constant',
ab: function() { return a+b }
}
Ok, here's a WAY to do it. I don't know if this will work for you since it doesn't recurse, however give it a try. This makes use of the reviver function to manipulate the data.
Note that the original string is a valid JSON string as you requested. As others have mentioned your examples are not valid JSON.
Example
var json = '{"a":"a constant","b":"[get:a] and b constant","c":"test"}';
var jsonobj = JSON.parse(json, function(key, value) {
//Ensure that value has the match function, ie. it's a string
if (value.match) {
//check for [get:xxx]
var matches = value.match(/\[get:([^\]]*\])/g);
//if something was found
if (matches) {
//Loop through each match.
for (i=0; i<matches.length; i++) {
//check if this object has that property
if (this[matches[i].substring(5, matches[i].length-1)]) {
//If it does, replace the matched text with
// the property's value.
// Note: It's split onto two lines for clarity on SO
value = value.replace(matches[i],
this[matches[i].substring(5, matches[i].length-1)]);
}
}
}
}
return value; //Return the possibly modified value
});
Edit
Also, I tested this on Opera 11, IE8 and FF 3.6.
var obj = {};
obj["a"] = "a constant";
obj["b"] = obj["a"] + " and b constant";
It's not pretty, and it's not JSON, but I think it's your only hope.
Otherwise, mark up the JSON differently to fit your use case:
var obj = {
a: "a constant",
b: "and b constant",
prependAB: true
}
...
if(obj.prependAB){
alert(obj.a + obj.b);
}
else{
alert(obj.b);
}
As far as I know, the short answer is no, though there are many ways to do this with more involved code. The obvious one is to put a
into a variable:
a = 'a constant';
var obj = {
a : a,
b : a + ' and b constant'
}
The function-based approach would need to be called, not evaluated when you define the object:
var obj = {
a : 'a constant',
b : function(){ return this.a + ' and b constant'; }
}
obj.b();
The other approach, also probably stating the obvious, is a two-pass version:
var obj = {
a : 'a constant'
}
obj.b = obj.a + ' and b constant';
Found a potential solution:
var obj = {
a : 'a constant',
b : obj.a + ' and b constant'
};
Thanks everyone for their tips! Upvoting all good suggestions.
精彩评论