Previously I thought that object's getter will be computed if and only if will be explicitly called:
const obj = {
log: ['a', 'b', 'c'],
get latest() {
console.log("checkpoint1")
if (this.log.length === 0) {
return undefined;
}
return this.log[this.log.length - 1];
}
};
console.log(obj.latest); // called!
However if we try to print the obj in console
console.log(obj)
checkpoint1 from 4th row will also printed! But I noticed this phenomena when run some UI tests without explicit calling of getters, so the printing of object in console on not only one case when getters could be implicitly called.
By why getter has been called?
Related
I have an object which I initialize with bunch of properties in node.js, spreading another object in, and at the end defining a getter.
The problem is the the getter uses this and all the properties defined on the object before the spread don't exist on this.
If I move the spread to the end or start of the object initialization, it works fine.
const obj = { a: 1 }
const obj2 = {
prop: 'a',
...obj,
prop2: 'b',
get test() {
return this.prop + this.prop2
}
}
console.log(obj2.test); // 'undefinedb'
What can possibly be the reason for that?
Thanks
I once again stumbled over a behavior in Javascript that I don't understand. I need to update properties of an object as soon as a variable outside of the object is changed. The external variable is referenced in the object properties so I thought all I had to do is to change the variable externally and automatically have the property values changed.
Here's a simplified version of what the code looks like:
var serverPath = "123/";
var GetCurrentProductionApiConfig = {
URL: {
GetStart: serverPath + 'GetCurrentProduction?returnValue=start&',
GetEnd: serverPath + 'GetCurrentProduction?returnValue=end&',
Get: serverPath + 'GetCurrentProduction?returnValue=start&'
}
};
serverPath = "456/";
console.log(GetCurrentProductionApiConfig.URL.GetStart);
This will result in:
123/GetCurrentProduction?returnValue=start&
Is it because the variable has been copied (passed by value) rather than having a pointer on it (passed by reference)? And which way would be the correct one to update the properties?
Everything in JavaScript is pass by value however, it happens that the value of an object is its reference. However, the important thing here is that for primitives, will not get changes when a referenced variable changes:
var a = "world";
var obj = {
b: "hello" + a //evaluated once
}
a = "universe"; //does not modify obj.b which references a
console.log(obj.b); //helloworld
In order to have a dynamically evaluated string, you need to call a function or a method:
var a = "world";
var obj = {
b: function() {
return "hello" + a //evaluated every time the function is executed
}
}
console.log(obj.b()); //helloworld
a = "universe"; //will influence obj.b
console.log(obj.b()); //hellouniverse
However, that looks a bit "dirty" since it forces the caller to know to evaluate the property every time. It can also introduce inconsistency if some properties are plain strings, others functions and it's especially annoying if a property has to change from one to the other - you need to modify every place that calls this code to change, say, obj.c to obj.c().
Instead, using ES6+ you can define a getter for a property that will do the same as before but will hide the function call, so any time you read a property you actually evaluate code to return the result:
var a = "world";
var obj = {
c: "plain property"
}
Object.defineProperty(obj, 'b', {
get: function() {
return "hello" + a //evaluated every time the property is read
}
});
console.log(obj.b); //helloworld
a = "universe"; //will influence obj.b
console.log(obj.b); //hellouniverse
console.log(obj.c); //plain property
I'm trying to delete an object property:
var test = {abc: 1};
console.log(delete test.abc); //works fine and returns 'true'
The following construct drives me crazy
function deleteNode(_node) {
console.log(delete _node);
}
deleteNode(test.abc); // does not work and returns 'false'
Why? I read many questions on stackoverflow regarding trouble with delete and read most of the typical links provided. But I can't find a solution to this simple problem...
Deleting dynamic props of an object could be achieved like this:
function deleteNode(obj, key) {
delete obj[key]
}
See the delete docs for more details.
When having a "path" like "a.b.c" you can use lodash unset which deletes nested entries:
var object = { 'a': { 'b': { 'c': 7 } } };
_.unset(object, 'a.b.c');
Use of eval is discouraged .
var test = {abc: 1};
function deleteNode(_node) {
console.log(delete _node);
}
deleteNode(test.abc);
When you invoked deleteNode above, test.abc already resolved to 1 before being passed to function. deleteNode is technically invoking delete 1. And according to ES standard, deleting a function argument directly results in false or gives an error in strict mode.
"use strict";
var test = {a: 1};
function del(a) {
console.log(delete a);
}
del(test.a);
You will need to pass the object and key as different arguments to method.
var test = {abc: {a: 1, b: 2, c: {d: 1}}};
function deleteNode(obj, key) {
console.log(eval('delete obj.' +key));
}
deleteNode(test, 'abc.c.d');
console.log('test is', test)
For the following syntax
a = {
get p() {
alert(1)
}
};
alert(a.p);
It prompts me 1, than undefined.
For
a = {
set p(x) {
alert(x)
}
};
alert(a.p);
It prompts me undefined.
I do not totally understand the behaviour,
what does
a = {
get p() {
alert(1)
}
}
and
a = {
set p(x) {
alert(x)
}
};
mean?
There are two types of object properties: data properties and accessor properties. Accessor properties are accessed by getters and setters.
Your object a is intended as object with accessor property which called p.
Normally, such objects are declared in the following way:
a = {
_p: 'my value', // intended as private
get p() {
return this._p;
},
set p(x) {
this._p = x;
}
};
console.log(a.p); // gives 'my value'
a.p = 'new value';
console.log(a.p); // gives 'new value'
Another way is to use Object.defineProperty() method which lets you to set all needed properties attributes. Like this:
var a = {p: 'my value'};
Object.defineProperty(a, 'p', {
get: function() { return this.p; },
set: function(newValue) { this.p = newValue; },
enumerable: true,
configurable: true
});
because p() method returns nothing hence it returns undefined
if you do
a={get p(){alert(1); return 2;}};
alert(a.p);
it will alert 1 and then 2 since this p() method returned 2
{get p(){alert(1)}}
this is an object that has a getter p
when you use a.p it will use that getter to retrieve some value
so when you do alert(a.p); it first call the getter, so alert 1, then alert the returned value undefined.
[Edit] - You changed your original question so this answer doesn't cover everything.
p is a getter function - It is called whenever you access the p property. In your getter you have alert(1).
The getter function doesn't return anything. Thus, p is undefined. So the alert(a.p) alerts undefined.
Thus, your program does:
Get value of a.p: alert(a.p)
Calls p getter function. Which has alert(1)
p getter function returns nothing
Thus alert(a.p) alerts undefined
I'm trying to access the properties of this object:
var obj = {hello: 1, world: 2};
This gives me back undefined:
function foo(a) {
for(property in a) {
console.log(a.property);
}
return "foo";
}
foo(obj);
This gives the intended result:
function bar(a) {
for(property in a) {
console.log(a[property]);
}
return "bar";
}
bar(obj);
Why does the call to foo not work, while the call to bar allows me to access the properties?
Because a.property is the same as a['property'], not a[property]. So you actually try to access the property "property".
Your second code snippet uses the variable property, the former uses the property property.