This question already has answers here:
Self-references in object literals / initializers
(30 answers)
Closed 8 years ago.
I am trying to do something like this:
var obj = {
a: 5,
b: this.a + 1
}
(instead of 5 there is a function which I don't want to execute twice that returns a number)
I can rewrite it to assign obj.b later from obj.a, but can I do it right away during declaration?
No. this in JavaScript does not work like you think it does. this in this case refers to the global object.
There are only 3 cases in which the value this gets set:
The Function Case
foo();
Here this will refer to the global object.
The Method Case
test.foo();
In this example this will refer to test.
The Constructor Case
new foo();
A function call that's preceded by the new keyword acts as a constructor. Inside the function this will refer to a newly
created Object.
Everywhere else, this refers to the global object.
There are several ways to accomplish this; this is what I would use:
function Obj() {
this.a = 5;
this.b = this.a + 1;
// return this; // commented out because this happens automatically
}
var o = new Obj();
o.b; // === 6
This should return the correct values:
function () {
var aVar = 5;
var bVar = aVar + 1;
return {
a : aVar,
b : bVar;
}
}();
As it turns out you can't reference an object inside another object unless the first one is a function. But you can do it this way.
var obj = {
a: 5
}
obj.b = obj.a + 1; // create field b in runtime and assign it's value
If you console.log(obj) you will have
obj = {
a: 5,
b: 6
}
This way you keep the object literal structure for the remaining part of the code
No, in your example, the value of this doesn't refer to the object literal.
You'll need to assign a value to b after the object has been created in order to base it on another property in obj.
in chrome debugger
> var o = {a: 5, b: this.a+1}
undefined
> o.b
NaN
> o.a
5
No. this will take the same meaning as it would outside the definition.
Related
This question already has answers here:
variable binding inside an object
(2 answers)
Closed 2 years ago.
While trying to understand how javaScript resolve variable, i wrote this code:
const a = 0;
var obj = {a: 1, foo: function(){console.log(a);}};
obj.foo();
I know that javaScript, like most of the programming languages, use the lexical/static scope to resolving variables.
But in this example, the lexical scope outside of foo function is obj scope and not global scope.
So why do i get output 0 instead of 1 ?
the lexical scope outside of foo function is obj scope and not global scope.
There is no such thing as "obj scope" or "object scope". In Javascript, every variable name (or identifier) is scoped to either a block (such as inside a loop, or inside a function block), or is global.
An object isn't a block. Putting a property on an object does not create a new identifier; referencing such a property name as if it were a standalone variable does not work, because it's not an identifier in scope.
The only time in which something like this would be possible would be if you used with and referenced the property as if it was a standalone variable inside the with block, but with should never be used.
const a = 0;
var obj = {
a: 1,
foo: function() {
console.log(a);
}
};
with (obj) {
console.log(a);
}
In an object with {a: 1} the 'a' is a string, not a variable. It does not assign 1 to 'a'. Instead it sets a key/value pair equivalent to { "a": 1 }.
It has nothing to do with scope. The variable a defined in the first line is the only variable of that name and never has its value changed in the code you gave.
Note also that you defined it as const meaning it cannot be assigned a different value.
If you need reference the a object property, is necessary use this.a, because a without this is the global variable.
const a = 0;
var obj = {a: 1, foo: function(){console.log(this.a);}};
obj.foo();
Because there is only one a, and it's declared on your first line.
In order to use this object's variables, you have to use this. For example:
const a = 0
var obj = { a: 1, foo: function() { console.log(this.a) } }
obj.foo(); // 1
When you use this.a, that's the same thing, if you use obj.a outside of this object.
To understand this better, you can check the example below:
const mark = 10
const obj = {
name: 'Sardor',
mark: mark,
setMark: function(num) { this.mark = num },
getMark: function() { console.log(this.mark) }
}
obj.getMark() // 10
obj.setMark(8)
obj.getMark() // 8
console.log(mark) // 10
It means, that you filled mark by the date of num. Then you called .setMark() function of obj and changed its value to 8. But you didn't change the variable mark, that is outside of obj. That's why finnaly you have 8 in obj.mark and 10 in mark.
Advice: read more about this
This question already has answers here:
Why can I change a constant object in javascript
(12 answers)
Closed 9 months ago.
In JavaScript:
const a = 6;
a = 2; // Error
const o = {};
o = 7; // Error
o.a = 5; // Good. Why?
const o = {a:1};
o.a = 2; // Good. Why?
I found people sometimes define a const object but later change its value. Why a const can be changed after its definition?
A variable declared with const means one thing: the standalone variable name cannot be reassigned with = later.
In contrast, o.a = 5; is not reassigning the variable name - it's mutating the content of the object, but it's not changing what the o variable points to in memory.
To prevent reassignment of a variable name, use const. To prevent mutation of an object is something entirely different - for that, you'd need something like Object.freeze or manipulate objects using immutable-js.
In the first case, a is const and cannot be reassigned. In the second and third, the object o is const so that object cannot be assigned another value, but its properties are not const. See here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object's contents (e.g., its properties) can be altered.
const variables aren't enforced to be immutable.
From MDN:
Constants are block-scoped, much like variables defined using the let statement. The value of a constant can't be changed through reassignment, and it can't be redeclared.
Emphasis mine.
o.a = 5 isn't reassigning o; it's reassigning a property in o.
For adding more information from the other answers, if you want to define a constant object property. You can try these ways:
const o = {
get a() {
return 1;
}
};
o.a = 2;
// 1
console.log(o.a);
const o2 = {};
Object.defineProperty(o2, 'a', {
value: 1,
writable: false,
enumerable: true,
configurable: true
});
o2.a = 2;
// 1
console.log(o2.a);
This question already has answers here:
Self-references in object literals / initializers
(30 answers)
Closed 8 years ago.
I am trying to do something like this:
var obj = {
a: 5,
b: this.a + 1
}
(instead of 5 there is a function which I don't want to execute twice that returns a number)
I can rewrite it to assign obj.b later from obj.a, but can I do it right away during declaration?
No. this in JavaScript does not work like you think it does. this in this case refers to the global object.
There are only 3 cases in which the value this gets set:
The Function Case
foo();
Here this will refer to the global object.
The Method Case
test.foo();
In this example this will refer to test.
The Constructor Case
new foo();
A function call that's preceded by the new keyword acts as a constructor. Inside the function this will refer to a newly
created Object.
Everywhere else, this refers to the global object.
There are several ways to accomplish this; this is what I would use:
function Obj() {
this.a = 5;
this.b = this.a + 1;
// return this; // commented out because this happens automatically
}
var o = new Obj();
o.b; // === 6
This should return the correct values:
function () {
var aVar = 5;
var bVar = aVar + 1;
return {
a : aVar,
b : bVar;
}
}();
As it turns out you can't reference an object inside another object unless the first one is a function. But you can do it this way.
var obj = {
a: 5
}
obj.b = obj.a + 1; // create field b in runtime and assign it's value
If you console.log(obj) you will have
obj = {
a: 5,
b: 6
}
This way you keep the object literal structure for the remaining part of the code
No, in your example, the value of this doesn't refer to the object literal.
You'll need to assign a value to b after the object has been created in order to base it on another property in obj.
in chrome debugger
> var o = {a: 5, b: this.a+1}
undefined
> o.b
NaN
> o.a
5
No. this will take the same meaning as it would outside the definition.
Let's say I have two objects like
var a = {
b: 1,
c: this.b
};
And
var funcObj = {
b : function() {
return 1;
},
c: function() {
console.log(return this.b())
}
}
On logging these two like
console.log(a.c)//results undefined
console.log(funcObj.c()) //results 1
Why can't the first function use the this property but the second one can?
I am really confused.
The answer depends on what this refers to in each context. In JavaScript, this is bound to whatever object was on the left of the dot (.) when the current function was called. If we're not in a function, things get a little hairier -- this is either the global window object or undefined, depending on the environment.
In your first example, the value of this is dependent on the surrounding context. As JavaScript builds your object a, it evaluates this.b. Whatever object this is currently bound to has no b property, so the c property is set to undefined.
In your second example, when you call funcObj.c() the this in the function gets bound to funcObj. So, when you ask for the b property, you get the b you defined above. The fact that funcObj.b is a function is actually irrelevant. The following would work just as well:
var funcObj = {
b : 1,
c: function() {
console.log(return this.b)
}
}
You cannot refer to other properties in the declaration as part of a Javascript literal declaration. So, in your Javascript literal declaration:
var a = {
b: 1,
c: this.b
};
this is not set to what you want and a has not yet been initialized yet so you can't refer to it either. There is simply no way to reach the other properties at the time of the literal declaration. This is a limitation of the current specification for Javascript. You could do this instead:
var a = {
b: 1
};
a.c = a.b;
because a is fully formed at that point so you can then reference other properties in it.
Or, in modern browsers, you could even use a getter to get the "live" version of b like this (which isn't exactly the same functionality as you were asking for since it's a "live" version of b that will track it's value), but shows you another possibility:
var a = {
b: 1,
get c() {
return b;
}
};
console.log(a.c); //results 1
In your second example:
var funcObj = {
b : function() {
return 1;
},
c: function() {
console.log(return this.b())
}
}
console.log(funcObj.c()) //results 1
You are calling funcObj.c() and that will set the value of this inside of c to funcObj so thus you can reference other properties via this.
The main difference here is that this is not set to the object inside of Javascript literal definition (your first example), but this is set to the object when you invoke a method as in funcObj.c().
I know this post is a bit old, but I came across it while trying to figure out how to solve a similar issue.
I was wanting to do something like:
const x = {
a: 12,
b: a + 1
}
console.log(x) //results undefined
(That's extremely simplified compared to what I was actually doing, but the principle is the same.)
My solution was to first create a function that would build the object I wanted, then pass in the primary value I was trying to act on (in this example, the value in 'a'):
function buildObj (val) {
const response = {
a: val,
b: val + 1
};
return response;
}
And then:
const x = buildObj(12)
console.log(x) // results { a: 12, b: 13 }
Once x has been initialized, any subsequent attempt to access
x.a
or
x.b
will return the values stored therein.
If a future searcher comes across this question because they're wanting to take an action on a value stored in a nested key within the same object, hopefully this will help.
This question already has answers here:
Self-references in object literals / initializers
(30 answers)
Closed 8 years ago.
Why can't i do something like this in javascript?
var big = { a:1, b:2, c:3, d:big.a }
How can an object's one property access another?
//--------------------------------edited as below ----------------------------------
Thanks for all the answers, now i found another question:
when i do this:
var big = {
a : 1,
b : 2,
c : 3,
d : this.a
}
console.log(big.d);
It's undefined
However, when i do this:
var big = {
a : 1,
b : 2,
c : 3,
d : function(){console.log(this.a)}
}
big.d();
It logs out 1
I wonder what's going on here, is it because it is a function in the second code somehow makes the 'this' accessible?
Thanks.
you can do this
var big = { a:1, b:2, c:3};
big.d = big.a;
In your code when you are using d:big.a it is still not defined i'e. big is not defined
Try this
var big = new function ()
{
this.a = 1;
this.b = 2;
this.c = 3;
this.d = this.a;
}
alert(big.a);
alert(big.b);
alert(big.c);
alert(big.d);
Hope this helps.
Since the variable big to get big.a hasn't been declared yet when you actually declare big. In this case you should inject the object d afterwards.
var big = { a:1, b:2, c:3 };
big.d = big.a;
You can't do it in the object literal. This is because the right hand side of the = is evaluated before the assignment takes place. Javascript first creates an object with the properties given and then assigns it to the variable. Therefore, at the point when you attempt to access big.a, the assignment has not taken place, so big is undefined and you get an error because you cannot access the properties of undefined.
You need to assign big.d after the assignment:
var big = { a:1, b:2, c:3};
big.d = big.a;