I hope the day finds you well.
So I have an object with no properties. I'm trying to add multiple properties to this object using a loop. Each property added to the loop will appear in the object multiple times depending on how many times the loop runs, with each new property incremented by 1.
So I have something like this:
myObject = { };
for(i = 0; i < 2; i++){
myObject.propA + i = foo;
myObject.propB + i = bar;
};
Which I want to yield something like this:
myObject.propA0 = foo;
myObject.propB0 = bar;
myObject.propA1 = foo;
myObject.propB2 = bar;
Giving a nice stack of objects generated on the fly depending on how many times the loop runs. But I don't seem to be getting this. So how exactly do I feed the variable from the loop to the property when it's created and assigned?
Try using square bracket notation for the names
myObject['propa' + i] = foo;
As other users said, you have to use bracket notation to refer to properties by their name strings:
myObject['propA' + i] = 'foo';
But why don't you use an array of objects, instead of a single object with similar, numbered property names? Something like this:
var myArray = [];
for(i = 0; i < 2; i++){
myArray.push({
propA: 'foo',
propB: 'bar'
});
};
This should produce:
[
{ propA: 'foo', propB: 'bar'},
{ propA: 'foo', propB: 'bar'}
]
It looks way cleaner, in my opinion.
Use the array-access method to set the properties.
myObject = { };
for(i = 0; i < 2; i++){
myObject['propA' + i] = foo;
myObject['propB' + i] = bar;
};
you might use
object['popA'+i]=...
to create a standard property or either use a getter/setter property, in this case you need to use
Object.defineProperty(object, *propertyname*, *propertyDescriptor*).
The latter gives you more options on the created property.
All details here :
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty
Related
Suppose I have an object (baz) of variable contents. How can I assign a sub-object (foo) with a key (baz) to that object in one line?
Examples:
var baz = {}
baz.foo.bar = 1;
console.assert(baz === { foo: { bar: 1 } });
(or, in the case where foo is already defined)
var baz = { foo: { 1: "b" } };
baz.foo.bar = 1;
console.assert(baz === { foo: { 1: "b", bar: 2 } });
It's possible to put all in one line, though personally I wouldn't recommend it. You're technically doing two pretty different things:
Assign an object as a property if the object doesn't exist yet
Assign a property if the object already exists, mutating the existing object
You can assign baz.foo or the empty object to baz.foo, then assign the bar property value to the resulting object:
const baz = {};
(baz.foo ??= {}).bar = 1;
console.log(baz.foo.bar);
const baz2 = {};
(baz2.foo ??= {}).bar = 1;
console.log(baz2.foo.bar);
I'd prefer
// Create the object if it doesn't exist yet
baz.foo ??= {};
// Assign the new nested value
baz.foo.bar = 1;
Code readability is more important than golfing in most cases.
For the first case :
baz.foo = {bar :1}
And your code works for the second case
(Note that the following code outputs false :
a = {b:1}
console.log(a==={b:1})
)
Is there a way in JavaScript to discover the object that an attribute belongs to? I know that sounds ridiculous, here's an example:
Obj = {};
Obj._name = "name";
var x = Obj._name;
In this example, is there a way to discover what object 'x' refers to?
Thank you
Not really, no - there's no back-reference checking or anything like that available in JS.
The only way this would kind of work would be if you had access to all the objects in question, in some kind of a collection, and could check each one for the property value.
This just returns the first object with a value that matches though, it's not guaranteed to be the source of the value.
var myObjs = [
{name: 'one'},
{name: 'two'},
{name: 'three'}
];
function findObjWithVal(val, objs) {
for (var i = 0; i < objs.length; i++) {
for (var p in objs[i]) {
if (objs[i].hasOwnProperty(p) && objs[i][p] === val) {
return objs[i];
}
}
}
}
console.log(findObjWithVal('two', myObjs)); // [object Object] { name: "two" }
What you're asking for is only really possible in a tight-set grouping of objects, with unique property values, where you know x is always a property value of one of the objects from the set, and no other object will have that property value. Pretty specific use case.
If you simply want the object to be attached to the string variable, you could do something like this:
var Obj = {
_name: 'Chad',
_address: '123 Main Street'
};
function string(val, obj) {
var s= new String(val);
s.obj= obj;
return s;
}
var x = string(Obj._name, Obj);
document.body.innerHTML= x + ' ' + x.obj._address; //Chad 123 Main Street
Referring to x would return Chad. But you have access to all the object's properties by referring to x.obj.
Say I have this function:
function doSomething(uno, dos, tres) {
// do something
}
and this object:
{
dos: 'foo',
tres: 'bar',
uno: 'baz'
}
How do I call doSomething given this mapping? I tried using apply, but it seems that apply must take a list instead of an object.
You can refer each property in the object as given above using . as given below.
doSomething(obj.uno, obj.dos, obj.tres)
Function.apply can only be used to apply an array-like object1 to a function call. There is no equivalent to Pythons "keyword argument expansion" and this must be done manually:
var opts = {
dos: 'foo',
tres: 'bar',
uno: 'baz'
}
doSomething(opts.uno, opts.dos, opts.tres)
If we started with an array-like object:
var arr = ['baz', 'foo', 'bar']
doSomething.apply(window, arr)
Or putting the two together (so that the composition of to a parameter sequence can be handled earlier):
var arr = [opts.uno, opts.dos, opts.tres]
doSomething.apply(window, arr)
While it may be possible (with non-obfuscated code) to use Function.toString2 to extract the parameter names, do some parsing, and then write some code to "apply" a general object (or construct an array that is then applied), this is not supported directly by the ECMAScript specification.
1 An array-like object is one that has a length and properties named 0..length-1. (Old versions of FF had a bug, but that has been fixed for a long time.)
2 The wording of the specification ("An implementation-dependent representation of the function is returned. This representation has the syntax of a FunctionDeclaration..") makes me believe that a conforming ES5 implementation ought to produce output usable for this purpose - however, this will likely vary by implementation and I have not explored such usage in practice.
You can try using:
function doSomething() {
for (var i = 0, l = arguments.length; i<l; i++) {
//dosomething
console.log(arguments[i]);
}
}
obj=['foo', 'bar', 'baz'];
doSomething.apply(null, obj);
Apply accepts array as second parameter but
if you insist on using object you can easily convert this object to Array and then use it with apply.
function objectToArray(obj) {
var arr = [];
for (field in obj)
arr.push(field);
return arr;
}
You can do something like this:
Function.prototype.applyNamed = function (g, argArr) {
var self = this;
var argNames = self.toString().match(/function\s+\w*\s*\((.*?)\)/)[1].split(/\s*,\s*/);
var applyArgs = [];
for(var i=0; i<argNames.length; i++){
applyArgs.push(argArr[argNames[i]]);
}
self.apply(self, applyArgs);
}
function doSomething(uno, dos, tres) {
console.log('uno = ' + uno);
console.log('dos = ' + dos);
console.log('tres = ' + tres);
}
var namedArgs = {
dos: 'foo',
tres: 'bar',
uno: 'baz'
};
doSomething.applyNamed(this, namedArgs);
Should print:
uno = baz
dos = foo
tres = bar
See the demo; credit.
Well, if you really want to, you actually can call a method using named parameters, but it requires parsing the string representation of the function. Whether or not you should use this technique is debatable, but here is how you would do it:
function doSomething(uno, dos, tres) {
// do something
}
var arguments = {
dos: 'foo',
tres: 'bar',
uno: 'baz'
}
function callFunction(fn, namedArguments) {
var orderedArguments = [];
var parameterRegExp = /\(([\s\w\$,]*)\)/;
parameterRegExp.exec(fn.toString())[1].replace(/\s/g, '').split(',').forEach( function(parameterName) {
orderedArguments.push(namedArguments[parameterName]);
});
return fn.apply(this, orderedArguments);
}
callFunction(doSomething, arguments);
I have a dynamically-created list of strings called 'variables'. I need to use these strings as the instance variables for an array of JavaScript objects.
var objectsArr = [];
function obj(){};
for (var i=0; i<someNumberOfObjects; i++ ) {
...
objectsArr[i] = new Object();
for (var j=0; j<variables.length; j++) {
objectArr[i].b = 'something'; //<--this works, but...
//objectArr[i].variables[j] = 'something'; //<---this is what I want to do.
}
}
The commented-out line shows what I am trying to do.
You can use the bracket syntax to manipulate the property by name:
objectArr[i][variables[j]] = 'something';
In other words, get the object from objectArr at index i then find the field with name variables[j] and set the value of that field to 'something'.
In general terms, given object o:
var o = {};
You can set the property by name:
o['propertyName'] = 'value';
And access it in the usual way:
alert(o.propertyName);
Use the bracket notation. This will get it done:
var objectsArr = [], ii, jj;
function Obj() {}
for(ii = 0; ii < someNumberOfObjects; ii += 1) {
objectsArr[ii] = new Obj();
for (jj = 0; jj < variables.length; jj += 1) {
objectArr[ii][variables[jj]] = 'something';
}
}
A couple of additional notes:
Javascript doesn't have block scope, so you must have two separate loop variables.
By convention, constructor functions like Obj should begin with a capital letter to signify that they ought to be used with the new keyword. In this case though, unless you need the objects to have a non-Object prototype, you could just use a plain object literal (objectsArr[ii] = {};).
I have a JS Object:
var testObj = new Object();
that has a property called volume1, so
testObj.volume1
has a value. How would I go about accessing that property by using something along the lines of
testObj.volume + "1"
To give it more context, the object actually has more properties, like
testObj.volume1, testObj.volume2 and testObj.volume3
and I want to access them using some iteration. I've tried playing with the window[] element, but have had not much success.
Thanks!
testObj["volume" + 1]
but you actually want an array here
testObj.volume = [...]
testObj.volume[1] = whatever
off topic it is considered better pratice to do
var testObj = {};
instead of
var testObj = new Object();
Use something in the fashion of testObj["volume" + "1"] ;)
The notations object.property and object["property"] are (almost) equivalent in javascript.
You can use for loop with in operation.
for(var PropName in testObj) {
var PropValue = testObj[PropName];
....
}
In case, you only want the property with the name started with 'value' only, you can also do this:
for(var PropName in testObj) {
if (!/^value[0-9]$/.match(PropName))
continue;
var PropValue = testObj[PropName];
....
}
OR if the number after the 'value' is always continuous you can just use a basic for loop.
for(var I = 0; I <= LastIndex; I++) {
var PropName = "value" + I;
var PropValue = testObj[PropName];
....
}
Hope this helps.