I would like to set a value to an object which is into a deep structure.
Let's say the value of myObject.language.settings.color should be red.
Out of my field of vision. Setting this value is based on the following way:
const myObject = {};
myObject.language = {};
myObject.language.settings = {};
myObject.language.settings.color = 'red';
That is a long process if the objects before do not exist yet.
I am looking for a shorter way to handle this. E.g. using myObject.language.settings.color = 'red'; but that would return an error, that says myObject is not defined.
Is there a simpler solution than that?
Related
I have a code that is supposed to read a google sheet and push these into an array but i keep encountering an error that proData.push is not a function What could I be missing in this code?
function getData() {
var values = SpreadsheetApp.getActive().getSheetByName("Projects").getRange("A1:O").getValues();
values.shift();
var proData = [];
values.forEach(function(value) {
var proData = {};
proData.project_state = value[0];
proData.project_name= value[4];
proData.project_code= value[5];
proData.end_date= value[2];
proData.push(proData);
})
Logger.log(JSON.stringify(proData));
return proData;
}
I will appreciate help in looking at this.
This line tells the whole story:
proData.push(proData);
You're trying to push an object onto itself? Clearly this is an indication that something is wrong. So let's look at where you define proData:
var proData = {};
That at least explains the error. proData is an object, not an array. And an object indeed doesn't have a function called push. You may have thought it was an array, because you defined an identically named array here:
var proData = [];
But for the line where you call .push, how is the system to know which variable you intend for what purpose? In a higher scope you have an array named proData, but in the current scope of this operation you obscured that with an object named proData. And in doing so made the array inaccessible within the scope of the function passed to .forEach.
To avoid confusing both the JavaScript engine and yourself in this matter, simply use different variable names. Re-naming the variable in the smaller scope has a lower impact, so that's a good candidate. (Though it's not always the best choice. If the variable in the higher scope is semantically not clear about what it contains then it should be re-named.)
Something like this:
values.forEach(function(value) {
var pd = {};
pd.project_state = value[0];
pd.project_name = value[4];
pd.project_code = value[5];
pd.end_date = value[2];
proData.push(pd);
});
Is it possible to keep an object reference without using an holder object in javascript?
Currently when an object gets overridden I sometimes lose the reference to the "current" object state illustrated in the snippet below;
Is there a way to put a "pointer" in an array or not?
EDIT
To the questions asked:
What I have in the objects I have are references to form fields. Some of these are text fields, some of them are textareas, some of them checkboxes.
I wish to keep a map next to the direct referene of what type they are.
basicaly it would be
obj {
this.text1 = createTextField();
this.text1.datepicker();
this.text2 = createTextField();
this.area1 = createArea();
this.check = createCheck();
this.datefields = [this.text1];
this.checkboxes = [this.check];
}
So I can use the datefields/checkboxes array as a checkpoint to validate against which type a field is/should behave.
Currently I use
function datefields() { return [this.text1]; };
But I'd like to know if there's a better way to do this than to intantiate a new array when I need to check it.
I know there is a way with observers to mimic pointer behaviour, and i've fiddled with those and have some good results with that, i'm just curious if there are other ways i'm not aware of.
function myObject() {
this.myvalue = null;
this.arr = [this.myvalue];
}
myObject.prototype.alter = function() {
this.myvalue = "hello";
}
var x = new myObject();
var elem = document.getElementById('results');
function log(message) {
elem.appendChild(document.createTextNode(message));
elem.appendChild(document.createElement('br'));
}
log("x.myvalue = "+x.myvalue);
log("x.arr[0] = "+x.arr[0]);
log("calling alter");
x.alter();
log("x.myvalue = "+x.myvalue);
log("x.arr[0] = "+x.arr[0]);
<div id="results"></div>
Simple answer: Only objects (including all subtypes) are passed by reference in JS. All other simple values are copied.
For a bit more detail I would recommend reading You Don't Know JS: Types & Grammer but specifically the section Value vs Reference in Chapter 2:
In JavaScript, there are no pointers, and references work a bit differently. You cannot have a reference from one JS variable to another variable. That's just not possible.
Quoting further on:
Simple values (aka scalar primitives) are always assigned/passed by value-copy: null, undefined, string, number, boolean, and ES6's symbol.
Compound values -- objects (including arrays, and all boxed object wrappers -- see Chapter 3) and functions -- always create a copy of the reference on assignment or passing.
There are plenty of examples included to show these points. I would highly recommend reading through to get a better understanding of how values/references work in JS.
There is no pointers in Javascript, though you could cheat a little using a wrapper object. Here is a minimal implementation of such an object:
var Wrapper = function (value) {
this.value = value;
};
Wrapper.prototype.valueOf = function () {
return this.value;
};
Then you may use it in place of the original value:
function myObject() {
this.myvalue = new Wrapper(null); // wrapper
this.arr = [this.myvalue];
}
myObject.prototype.alter = function() {
this.myvalue.value = "hello"; // notice the ".value"
}
The rest of your code needs no tweaks.
Things will be clear when you see the following example.
function AddStyle(prob, value) {
Elem = document.getElementById('box');
Elem.style.prob = value;
}
// Here is, when usage.
AddStyle('backgroundColor', 'red');
As you see in the previous example, we have two parameters (prob is the property Name), (value is the value of property).
That example doesn't work, There are no errors Occur also.
I'm certain that the problem in this line Elem.style.prob = value; and especially here style.prob.
Variables aren't resolved in that way. Basically, you're code is looking for a property of style literally called prob. You'll have to access the property using brackets, since objects are indexed by property name. Something like:
Elem.style[prob] = value; // Access the property of style equal to the value of prob
This would be equivalent to:
Elem.style['backgroundColor'] = value;
Which would be equivalent to:
Elem.style.backgroundColor = value;
Demo
If I do this,
var element = {};
alert(element);
element[name] = "stephen";
alert(element.name);
Why doesn't element.name work?
When using bracket notation, (unless it's a variable) it needs to be in qoutes, like this:
var element = {};
alert(element);
element["name"] = "stephen";
alert(element.name);
You cant test it out here. To explain what I mean by "unless it's a variable", this would also work:
var myVariable = "name";
element[myVariable] = "stephen";
Because name should be in quotes.
This works:
var element = {};
alert(element);
element['name'] = "stephen";
alert(element.name);
Try it.
This is the reason why you may want to get an object's property dynamically. For example:
You have a variable, but you can't be sure of its value. The server send you the variable value so you should write like this.
obj[name].age // Here the name is a variable, and it can be changed in every page refresh, for example.
But if you want to set obj['name'] = 'Lorenzo' you have to use quotes.
Think like obj[name] is used for set, obj['name'] is used for get.
Weird problem here, I'm trying to use a global function to update my settings object, example:
var Settings = new Object;
Settings.savepos = 'true';
function UpdateSetting(obj,value){
eval("Settings.obj = value");
alert(Settings.savepos);
}
The obj is the key of the object, meaning if I call the function with
UpdateSetting('savepos','false')
the alert will always just give me true, how do I convert that eval or any alternative so it will update settings object's key with the value?
You are setting Settings.obj, not setting.savepos.
Try this instead:
function UpdateSetting(obj,value){
Settings[obj] = value;
alert(Settings.savepos);
};
You are always changing the "obj" key of the object to equal value, which is likely to be undefined (or, at least, not defined to what you want) in the context eval() executes it in. So, you have two options. First, you can keep using eval() (although i don't recommend it because it's more pain than necessary):
var Settings = new Object;
Settings.savepos = 'true';
function UpdateSetting(obj,value){
eval("Settings."+obj+" = '"+value+"'");
alert(Settings.savepos);
}
Or, as numerous other have suggested, you can use the array operator[] to access the property by key:
var Settings = new Object;
Settings.savepos = 'true';
function UpdateSetting(obj,value){
Settings[obj] = value;
alert(Settings.savepos);
}
you dont need an eval
you're setting .obj, not .savepos (there is no interpolation for the string)
you may be calling it wrong.
I'm not exactly sure why you don't just set the value directly (eg. Settings.savepos=false;).
You can attach the function to that object to do something similar:
var Settings = new Object;
Settings.savepos = true;
Settings.UpdateSetting = function (prop,value){this[prop] = value;}
Settings.UpdateSetting('savepos',false);
You should be able to use array notation on the object. Underneath it's just a keyed hash.
Try:
Settings[obj] = value;
I'd also suggest passing values as they are, i.e. string, int, etc:
UpdateSetting('key_name', false);