How to use the "this" keyword in the JavaScript object notation (JSON) in the example below?
{
firstName: "Foo",
lastName: "Bar",
fullName: function () {
return this.firstName + " " + this.lastName;
}
}
The code above neither work with the this
keyword nor without it.
Why is that? The only working solution is to assign the JSON object to a variable and to use the variable in the code.
Is there something similar to the "this" keyword that can be used instead of it?
Any suggestions are welcome.
edit: As stated in the comments below, it's not JSON but "javascript object literal". Thank you for that hint. Nevertheless, my question still remains valid (for the javascript object literal).
invalid: The code above works as expected, thus fullName() returns "Foo Bar".
Unicode codepoints U+D800 to U+DFFF must be avoided: they are invalid in Unicode because they are reserved for UTF-16 surrogate pairs. Some JSON encoders/decoders will replace them with U+FFFD.
It means that the editor failed to get a response to the server or the response wasn't in a valid JSON format. Basically, if the editor can't communicate with the server, it will show this error message instead. To fix the problem, you essentially need to fix whatever is getting in the way of the communication.
It has no special meaning to JSON. This particular data uses it as a key string.
JSON Keys must be Valid Strings According to JSON.org, a string is a sequence of zero or more Unicode characters, wrapped in double quotes, using backslash escapes. Any valid string can be used as a JSON key. These keys must be enclosed in the double-quotes ( " ).
If I understand it, this actually may not be an invalid question (just a poorly asked one, with some mistakes), and is really potentially a little interesting. The JSON misnomer was an unfortunate distracting mistake, but really, he's asking how to dynamically have a property be equal to a dynamic result of other properties--i.e., why doesn't
x = {
a: "hello",
b: " ",
c: "world",
d: this.a + this.b + this.c
}
result in
x.d === "hello world"
?
Instead, what you find is that this
refers to window
there. This shows us that this
is only something gotten from inside a function, and not an intrinsic relational reference we can rely on outside of that context.
This is clearly why the asker then used a function, to get access to this
. However, I think the problem is then you get a function you have to call, where he actually wants text. (I might be extrapolating a bit there, not sure.)
One might be tempted to just use an IIFE, but that won't work either:
x = {
a: "hello",
b: " ",
c: "world",
d: (function() { this.a + this.b + this.c })()
}
x.d === NaN // undefined + undefined + undefined
What happens is that when when we call an IIFE, we create a new scope, with a new this
--also, it would only be run once, on object initialization, and wouldn't dynamically reflect those other value changes.
Because he said 'we have to assign the object to a variable and then use that', I assumed he had found a workaround wherein you just declare it twice, and on the second time it works if you're referring to properties on a global (so, x.a + x.b
), and provided the wrong example.
All of this goes to show that lexical scoping overtakes dynamic scoping here. Another naive way one might consider trying to work around this would be like this:
x = {
a: "hello",
b: " ",
c: "world",
d: (function() { this.x.a + this.x.b + this.x.c })()
// or maybe:
e: (function() { this.x.a + this.x.b + this.x.c }).call(this)
}
(Explanation: since this
refers to window
and x
is a global, and therefore property of window
(i.e., window.x === x
)... honestly we could also just omit this
here, but it helps illustrate what's going on here so I'll leave it.)
But no, that function is called while x
is being initialized, and so x
isn't yet defined in lexical scope until after that function call. or e
, 'this' is still window
.
What we learn here is that there is no way to access sibling properties at evaluation time of the object within Javascript, either.
Neat!
As a result, to achieve the desired goal, two separate statements are needed:
x = {
a: "hello",
b: " ",
c: "world"
}
x.d = x.a + x.b + x.c;
unless you desired the ability to have x.d dynamically respond with those values, instead of be the result of adding those values at this moment--then you'd just use the original code in the question, and have to evaluate it as a function.
... ...
As soon as I had finished writing the above, I remembered a javascript feature I've never used: getters and setters. Sure enough, they accomplish exactly what we're looking for here:
var hello = {
a: "hello",
b: "world",
get test() {
return this.a + this.b
}
}
// undefined
hello.test
// "helloworld"
hello.a = 'stuff'
// "stuff"
hello.test
// "stuffworld"
Of course, this is computationally equivalent to calling hello.test() and just making test a function, as in the original code. This getter can't be serialized just like a function can't, as far as JSON goes (though we established that isn't the point here, I just want to be clear). In the end, the only thing we really gained was the ability to omit parenthesis--and this won't serialize over JSON, to be clear, if that really was really an intentional part of the question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With