Related
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] = {};
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] = {};
As I understand objects are passed by reference in JavaScript (and primitives are passed by value?).
var a, b;
a = {
Foo: "Bar"
}
b = a;
a.Foo = "Other";
console.log(b.Foo); // "Other"
This worked similarly with arrays but did not work like I expect with functions:
var a, b;
a = function(){ return 20; }
b = a;
a = function(){ return 40; }
console.log(b()); // returns 20 ?
I'm confused because I thought functions are objects. Shouldn't the above example return 40?
In the first case, a.Foo = ..., You are changing the value of a property in the object, referred by both a and b. This is called mutating an object.
But in the second case, you are making a refer a new function object. Now, a and b are referring to different function objects.
That is why you are getting 20 in the second case.
First regarding the question in the title (which is actually different from what you demonstrate with the code examples):
"As I understand objects are passed by reference in JavaScript"
No, Javascript doesn't support passing parameter by reference at all. All parameters are passed by value, but the value can be a reference.
Example:
var a = { answer: 42 };
function f(x) {
alert(x.answer); // shows 42
x = { answer: 0 };
alert(x.answer); // shows 0
}
f(a);
alert(a.answer); // shows 42
As the parameter is passed by value, the variable x is separate from the variable a, so assigning a new object to x doesn't change the value of a.
Back to your code:
When you assign an object reference from a variable to another, it's the reference that is copied, not the object. You get two variables that reference the same object.
Either of the variables can be used to access members in the object, which your first code example demonstrates.
If you assign a new object to the first variable, you will replace the reference in the variable, you will not overwrite the object that it currently points to. The object is still intact, and the second variable still points to it. You get two variables that point to one object each, which your second code example demonstrates.
Further to #thefoutheye's answer, consider the following proof of your statement functions are objects:
var a, b;
a = function() { return 20; }
a.Foo = "Bar";
b = a;
a.Foo = "Other";
console.log(b.Foo); // "Other"
You are reassigning the variable a to a new function. That's not the same as changing a property value.
Try:
var a, b;
a = {Foo: function() {return 20;}};
b = a;
a.Foo = function() {return 40;};
console.log(b()); // returns 40
I'm trying to write a function that corrects the arguments of a function based on previously specified optional parameters. I've come to a problem though. It seems that I can't set variables via the arguments array unless they have been defined in any way before. The code below shows an example of the problem I'm facing.
function foo(a, b, c) {
arguments[0] = "lorem";
arguments[1] = "ipsum";
arguments[2] = "dolor";
console.log([a, b, c]);
}
foo(null); // ["lorem", undefined, undefined]
foo(null, null); // ["lorem", "ipsum", undefined]
foo(null, null, null); // ["lorem", "ipsum", "dolor"]
When logging arguments the result is always ["lorem", "ipsum", "dolor"] though.
Is there any way to solve this problem ?
I can't set a, b and c directly because a function called in foo wouldn't have access to these names.
My goal would look like something like this:
function foo(a, b, c) {
var rules = [];
// Rule for optional parameter 1 (b)
// If it equals true the value of b is shifted to the next parameter (c)
rules[1] = function(val) { return val !== "ipsum"; };
optionalize(rules);
console.log([a, b, c]);
}
foo("lorem", "dolor"); // ["lorem", undefined, "dolor"];
The arguments array isn't really an array but an "array-like" object. You can't change its length.
What you try to do is usually done using
a = a || "lorem";
or, if you don't want to replace any "falsy" argument, using
if (typeof a === "undefined") a = "lorem";
It is a bit peculiar, but is this what you had in mind?
function optionalize(fn, options) {
var i, key, rule;
for(i = 0; i < options.length; i += 1) {
key = fn.placement[i];
rule = fn.ruleset[key];
// If the rule exists and returns true, shift value to the right.
if(rule && rule(options[i])) {
options[i+1] = options[i];
options[i] = undefined;
}
// Assign the numeric index to an alphabet key.
// Depending on your use case, you may want to substitute a plain Object here and return that, instead of adding non-numeric properties to an Array.
options[key] = options[i];
}
}
// Test function
function foo(a, opts) {
opts = opts || [];
optionalize(foo, opts);
console.log([a, opts.b, opts.c]);
}
// Optional argument names, in the order that they would be received.
foo.placement = ['b', 'c'];
// Optionalize rules
foo.ruleset = {
b: function (val) { return val !== "ipsum"; }
};
// Demonstration
foo('lorem');
foo('lorem', []);
foo('lorem', ['dolor']);
foo('lorem', ['ipsum', 'dolor']);
As dystroy's answer has already indicated, the arguments variable isn't a real Array, and changing it may not be a good idea. I have provided a solution which does not rely on arguments and fulfills the criteria as far as could be possible using simple JavaScript.
The function foo is specified with a required argument a, followed by an Array of optional arguments named opts. An optionalize specification is set onto foo, through the placement and ruleset properties. The optionalize function takes this information and transforms the array's indices into usable name keys, applying the rules as necessary.
I'm not sure what you're trying to do but something like arguments[0] = a ? a : "lorem" and so on ?
You can convert arguments to an array
function foo () {
var arguments = Array.prototype.slice.call(arguments);
arguments.push(4);
console.log(arguments);
}
foo(1,2,3);
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] = {};