JavaScript - cannot set property of undefined - javascript

My code:
var a = "1",
b = "hello",
c = { "100" : "some important data" },
d = {};
d[a]["greeting"] = b;
d[a]["data"] = c;
console.debug (d);
I get the following error:
Uncaught TypeError: Cannot set property 'greeting' of undefined.
I'm trying to do something similar to an associative array. Why isn't this working?

you never set d[a] to any value.
Because of this, d[a] evaluates to undefined, and you can't set properties on undefined.
If you add d[a] = {} right after d = {} things should work as expected.
Alternatively, you could use an object initializer:
d[a] = {
greetings: b,
data: c
};
Or you could set all the properties of d in an anonymous function instance:
d = new function () {
this[a] = {
greetings: b,
data: c
};
};
If you're in an environment that supports ES2015 features, you can use computed property names:
d = {
[a]: {
greetings: b,
data: c
}
};

You have to set d[a] to either an associative array, or an object:
d[a] = [];
d[a] = {};
Without setting, this is what's happening:
d[a] == undefined, so you're doing undefined['greeting']=b; and by definition, undefined has no properties. Thus, the error you received.

The object stored at d[a] has not been set to anything. Thus, d[a] evaluates to undefined. You can't assign a property to undefined :). You need to assign an object or array to d[a]:
d[a] = [];
d[a]["greeting"] = b;
console.debug(d);

In ES6 you can use the spread operator, if d[a] is undefined it will just ignore, but if it has content it will keep it
d[a] = { ...d[a], greeting: b, data: c };
The accepted answer will override anything in d, which is not the behaviour we would always want

In javascript almost everything is an object, null and undefined are exception.
Instances of Array is an object. so you can set property of an array, for the same reason,you can't set property of a undefined, because its NOT an object

i'd just do a simple check to see if d[a] exists and if not initialize it...
var a = "1",
b = "hello",
c = { "100" : "some important data" },
d = {};
if (d[a] === undefined) {
d[a] = {}
};
d[a]["greeting"] = b;
d[a]["data"] = c;
console.debug (d);

d = {} is an empty object right now.
And d[a] is also an empty object.
It does not have any key values. So you should initialize the key values to this.
d[a] = {
greetings:'',
data:''
}

This occurs due to setting value to an object property without properly defining it's structure.
eg: The following code will give such error, because we are assigning value to an array. That can't be possible.
let boatNames = [];
boats.map(boat => {
while( i < boats.length){
boatNames[i].name = boat.boat.name;
i++;
}
})
To make it work, before setting some value to a property (boatNames[i].name = boat.boat.name;) make sure you define it first. like this... boatNames[i] = {};

Related

Why does JS desctructuring assignment work with numbers

As the title says, why does this code not throw a SyntaxError? I thought you could only destructure Objects
const {
a,
b
} = 0;
console.log(a, b); // undefined, undefined
When you access a property of a primitive, the primitive's object wrapper is used to see if such a property exists on the prototype. For example, Number.prototype.toFixed exists. So you could theoretically do something like
const {
toFixed
} = 0;
console.log(toFixed);
or
Number.prototype.a = 'foo'; // just for example, please never do this
Number.prototype.b = 'bar';
const {
a,
b
} = 0;
console.log(a, b);
It's not invalid syntax, it's just really weird.

How to update global object value?

I am not sure about best practice that how to deal with it:
const obj = {a: null}
function getObject(){
// I may return a, or anything that could be nested property
return obj.a
}
let v = getObject()
v = 'updated'
console.log(obj.a) // null
I expect a value co-operates with v assignment. I have seen with operator but people say avoid using it. So, what should I be using?
If a function returns the value of a field/variable then you get a reference to the object stored in that field/variable, not a reference to the variable itself. You either need to have getObject() return an object, which you then set the field value on, like so:
function getObject(){
return obj;
}
getObject().a = 'something';
Or you need to write a function that assigns the field value instead, like so:
function setValue(val) {
obj.a = val;
}
Another option would be to wrap your values in objects, so getObject never returns null, instead returning an empty object on which you set a field value, like so:
const obj = {a: {}}
function getObject(){
return obj.a
}
let v = getObject();
v.value = "foo";
// obj now equals {a: {value: "foo"}}
As written you're returning the value currently stored in a, saving that to a variable, then changing the value in the new variable. The value in obj remains unchanged.
You can access any Javascript object using dot like what you had in getObject , also you can set value to the object like this anyObject.key = value this will change the value of the key in the object.
const obj = new Object({ a : null })
Object.prototype.setA = function(a) {
this.a = a
}
obj.setA('hello world!')
console.log(obj)
If you want to update a global object values you need to access the object and assign it
const obj = {a: null}
function getObject(){
return obj.a
}
let v = getObject()
console.log(getObject()) //null
console.log(obj.a) // null
obj.a = "a" //you are now overriding what was null here
console.log(obj.a) //contains "a" now or whatever type you want it to be
I'd recommend you check this helpful tutorial: https://www.w3schools.com/js/js_objects.asp
Understanding JS variables is important:
let a = 1;
console.log(a); //1
a = 2;//overrides a
console.log(a); //2
What you are trying to achieve is not very clear but I would recommend to always mutate the global var to avoid errors and confusion.
Short answer:
you are changing the value of v and not changing the object referenced by v
Long answer:
If this was written in a class-based langauge (like C, java, or C++, etc.), this would also not change a. Because you are only changing what v points or reference to (in case of pointers).
In C :
void *v = (void*) &getObject() // v is equal to obj (or points to obj) obj
v = (void*) &some.thing.something() // v is now equal to some.thing.something() or points to some.thing.something()
// obj has not changed
print(obj.a) // null which is reasonable
// printf ("%s", obj.a); is the correct syntax in C
To actually change a you need to change the value of of the address in memory that is referenced by v
In C:
void *v = (void*) &getObject()
*v = (void *) some.thing.something()
print(obj.a) // now obj is equal to 'some.thing.something()'
// printf ("%s", obj.a); is the correct syntax in C
Now in your code why a is not changing ?
When it comes to Javascript, it is a langauge based on prototypes, rather than class-based
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model
Check the link above.
It is because of the same reason explained in the first C code above. You are just changing the value of v and not changing the object referenced by v
let v = getObject()
v = 'some.thing.something()'
console.log(obj.a) // null

Cannot set property 'addUser' of undefined [duplicate]

My code:
var a = "1",
b = "hello",
c = { "100" : "some important data" },
d = {};
d[a]["greeting"] = b;
d[a]["data"] = c;
console.debug (d);
I get the following error:
Uncaught TypeError: Cannot set property 'greeting' of undefined.
I'm trying to do something similar to an associative array. Why isn't this working?
you never set d[a] to any value.
Because of this, d[a] evaluates to undefined, and you can't set properties on undefined.
If you add d[a] = {} right after d = {} things should work as expected.
Alternatively, you could use an object initializer:
d[a] = {
greetings: b,
data: c
};
Or you could set all the properties of d in an anonymous function instance:
d = new function () {
this[a] = {
greetings: b,
data: c
};
};
If you're in an environment that supports ES2015 features, you can use computed property names:
d = {
[a]: {
greetings: b,
data: c
}
};
You have to set d[a] to either an associative array, or an object:
d[a] = [];
d[a] = {};
Without setting, this is what's happening:
d[a] == undefined, so you're doing undefined['greeting']=b; and by definition, undefined has no properties. Thus, the error you received.
The object stored at d[a] has not been set to anything. Thus, d[a] evaluates to undefined. You can't assign a property to undefined :). You need to assign an object or array to d[a]:
d[a] = [];
d[a]["greeting"] = b;
console.debug(d);
In ES6 you can use the spread operator, if d[a] is undefined it will just ignore, but if it has content it will keep it
d[a] = { ...d[a], greeting: b, data: c };
The accepted answer will override anything in d, which is not the behaviour we would always want
In javascript almost everything is an object, null and undefined are exception.
Instances of Array is an object. so you can set property of an array, for the same reason,you can't set property of a undefined, because its NOT an object
i'd just do a simple check to see if d[a] exists and if not initialize it...
var a = "1",
b = "hello",
c = { "100" : "some important data" },
d = {};
if (d[a] === undefined) {
d[a] = {}
};
d[a]["greeting"] = b;
d[a]["data"] = c;
console.debug (d);
d = {} is an empty object right now.
And d[a] is also an empty object.
It does not have any key values. So you should initialize the key values to this.
d[a] = {
greetings:'',
data:''
}
This occurs due to setting value to an object property without properly defining it's structure.
eg: The following code will give such error, because we are assigning value to an array. That can't be possible.
let boatNames = [];
boats.map(boat => {
while( i < boats.length){
boatNames[i].name = boat.boat.name;
i++;
}
})
To make it work, before setting some value to a property (boatNames[i].name = boat.boat.name;) make sure you define it first. like this... boatNames[i] = {};

JS: how to dynamically add attribute to object [duplicate]

My code:
var a = "1",
b = "hello",
c = { "100" : "some important data" },
d = {};
d[a]["greeting"] = b;
d[a]["data"] = c;
console.debug (d);
I get the following error:
Uncaught TypeError: Cannot set property 'greeting' of undefined.
I'm trying to do something similar to an associative array. Why isn't this working?
you never set d[a] to any value.
Because of this, d[a] evaluates to undefined, and you can't set properties on undefined.
If you add d[a] = {} right after d = {} things should work as expected.
Alternatively, you could use an object initializer:
d[a] = {
greetings: b,
data: c
};
Or you could set all the properties of d in an anonymous function instance:
d = new function () {
this[a] = {
greetings: b,
data: c
};
};
If you're in an environment that supports ES2015 features, you can use computed property names:
d = {
[a]: {
greetings: b,
data: c
}
};
You have to set d[a] to either an associative array, or an object:
d[a] = [];
d[a] = {};
Without setting, this is what's happening:
d[a] == undefined, so you're doing undefined['greeting']=b; and by definition, undefined has no properties. Thus, the error you received.
The object stored at d[a] has not been set to anything. Thus, d[a] evaluates to undefined. You can't assign a property to undefined :). You need to assign an object or array to d[a]:
d[a] = [];
d[a]["greeting"] = b;
console.debug(d);
In ES6 you can use the spread operator, if d[a] is undefined it will just ignore, but if it has content it will keep it
d[a] = { ...d[a], greeting: b, data: c };
The accepted answer will override anything in d, which is not the behaviour we would always want
In javascript almost everything is an object, null and undefined are exception.
Instances of Array is an object. so you can set property of an array, for the same reason,you can't set property of a undefined, because its NOT an object
i'd just do a simple check to see if d[a] exists and if not initialize it...
var a = "1",
b = "hello",
c = { "100" : "some important data" },
d = {};
if (d[a] === undefined) {
d[a] = {}
};
d[a]["greeting"] = b;
d[a]["data"] = c;
console.debug (d);
d = {} is an empty object right now.
And d[a] is also an empty object.
It does not have any key values. So you should initialize the key values to this.
d[a] = {
greetings:'',
data:''
}
This occurs due to setting value to an object property without properly defining it's structure.
eg: The following code will give such error, because we are assigning value to an array. That can't be possible.
let boatNames = [];
boats.map(boat => {
while( i < boats.length){
boatNames[i].name = boat.boat.name;
i++;
}
})
To make it work, before setting some value to a property (boatNames[i].name = boat.boat.name;) make sure you define it first. like this... boatNames[i] = {};

Is it necessary to create nested jSON objects before using it?

I think I've seen how to create a JSON object without first preparing it. This is how i prepare it:
obj = {
0:{
type:{}
},
1:{},
2:{}
};
Now I think I can insert a value like: obj.0.type = "type0"; But I'd like to create it while using it: obj['0']['type'] = "Type0";.
Is it possible, or do I need to prepare it? I'd like to create it "on the fly"!
EDIT
I'd like to create JS object "On the fly".
var obj = {};
obj.test = "test"; //One "layer" works fine.
obj.test.test = "test" //Two "layers" do not work... why?
obj = {
0:{
type:{}
},
1:{},
2:{}
};
Now i think i can insert value like: obj.0.type = "type0";
I guess you mean "assign" a value, not "insert". Anyway, no, you can't, at least not this way, because obj.0 is invalid syntax.
But I'd like to create it while using it: obj['0']['type'] = "Type0";
That's fine. But you need to understand you are overwriting the existing value of obj[0][type], which is an empty object ({}), with the string Type0. To put it another way, there is no requirement to provide an initialized value for a property such as type in order to assign to it. So the following would have worked equally well:
obj = {
0:{},
1:{},
2:{}
};
Now let's consider your second case:
var obj = {};
obj.test = "test"; //One "layer" works fine.
obj.test.test = "test" //Two "layers" do not work... why?
Think closely about what is happening. You are creating an empty obj. You can assign to any property on that object, without initializing that property. That is why the assignment to obj.test works. Then in your second assignment, you are attempting to set the test property of obj.test, which you just set to the string "test". Actually, this will work--because strings are objects that you can set properties on. But that's probably not what you want to do. You probably mean to say the previous, string value of obj.test is to be replaced by an object with its own property "test". To do that, you could either say
obj.test = { test: "test" };
Or
obj.test = {};
obj.test.test = "test";
You are creating a plain object in JavaScript and you need to define any internal attribute before using it.
So if you want to set to "Type0" an attribute type, inside an attribute 0 of an object obj, you cannot simply:
obj['0']['type'] = "Type0";
You get a "reference error". You need to initialize the object before using it:
var obj = {
0: {
type: ""
}
};
obj['0']['type'] = "Type0";
console.log(obj['0']['type']);
You could create your own function that takes key as string and value and creates and returns nested object. I used . as separator for object keys.
function create(key, value) {
var obj = {};
var ar = key.split('.');
ar.reduce(function(a, b, i) {
return (i != (ar.length - 1)) ? a[b] = {} : a[b] = value
}, obj)
return obj;
}
console.log(create('0.type', 'type0'))
console.log(create('lorem.ipsum.123', 'someValue'))
Is it necessary to create nested objects before using it?
Yes it is, at least the parent object must exist.
Example:
var object = {};
// need to assign object[0]['prop'] = 42;
create the first property with default
object[0] = object[0] || {};
then assign value
object[0]['prop'] = 42;
var object = {};
object[0] = object[0] || {};
object[0]['prop'] = 42;
console.log(object);
Create object with property names as array
function setValue(object, keys, value) {
var last = keys.pop();
keys.reduce(function (o, k) {
return o[k] = o[k] || {};
}, object)[last] = value;
}
var object = {};
setValue(object, [0, 'prop'], 42);
console.log(object);

Categories

Resources