javascript create object using multiple variables for multiple property name - javascript

how can i create object using multiple variables for multiple property name.
I am trying to create multiple versions of an object which has an init function. I have tried using the javascript 'new' function but in this case that does not work and the console notifies me this is because it is not a function. See the code for a clearer description of what I am trying to do.
for (a=1;a<=5;a++)
{
json.name={};
json.name[a]={};
for (b=1;b<11;b++)
{
json.name[a][b]={};
json.name[a][b]=$("input#c"+b+"r"+a).val();
}
//json.name.1.3 = the value from the input

The problem is the fact you keep writing over the variable in the loop.
Move json.name={}; outside the for loop.
var a, b, json;
json.name = {};
for (a=1; a<=5; a++) {
json.name[a] = {};
for (b=1; b<11; b++) {
json.name[a][b] = $("input#c"+b+"r"+a).val();
}
}
It also seems weird you are using objects and not arrays and that you are starting at one and not zero.

Related

If I pass an array into a JS function it doesn't seem to modify that array. Shouldn't it be passed by reference?

This Javascript function inside my class doesn't seem to modify the array that it's passed to it by reference:
this.filterEqualCities(this.birthCitiesNames, this.birthCitiesPositions);
filterEqualCities: function(citiesNames, citiesPos) {
var tempNamesArray = [];
var tempPosArray = [];
for(var i=0; i<citiesNames.length; i++) {
var name = citiesNames[i];
name = name.split(',')[0];
if(tempNamesArray.indexOf(name) == -1) {
tempNamesArray.push(name);
tempPosArray.push(citiesPos[i]);
}
}
citiesNames = [];
citiesPos = [];
for(var i=0; i<tempNamesArray.length; i++) {
citiesNames.push(tempNamesArray[i]);
citiesPos.push(tempPosArray[i]);
}
}
When you do:
citiesNames = [];
citiesPos = [];
the variables are no longer references to the original arrays that were passed in, now they're references to these two empty arrays.
If you want to clear out the original arrays, you can simply set their lengths:
citiesNames.length = 0;
citiesPos.length = 0;
To expand a bit upon #Barmar's excellent answer - the issue is that arrays and other objects are not really "passed by reference" in Javascript, even though it seems that way a lot of the time, and it's often described that way. They're passed by value, like all other variables - but that "value" is itself a "reference" to an actual value stored in memory, not to another variable itself.
So if you were to modify citiesNames, say by pushing a new element onto it, that would be reflected outside the function - because you'd be modifying that shared value to which both citiesNames variables (local and global) are references to.
But when you do citiesNames=[], you're taking the citiesNames local variable and reassigning it to a completely new value, and there's no way your other citiesNames variable can know about that.
This behaviour isn't unique to Javascript. Python certainly behaves the same way (and perhaps others too that I'm not as familiar with).

Looking for a good clear explanation for why this doesn't work

So I am learning Javascript and testing this in the console.
Can anybody come up with a good explanation why something like this does not work?
var students = ['foo', 'bar', 'baz'];
function forEach2(arr1) {
for (i = 0; i < arr1.length; i++) {
console.log(arr1[i]);
}
}
students.forEach2(students)
I get : Uncaught TypeError: students.forEach2 is not a function
For me it would seem logical to work but it doesn't
why?
forEach2 is not a function of students. students is an array containing 3 string values. just use forEach2 without students. before it.
var students = ['foo', 'bar', 'baz'];
function forEach2(arr1) {
for (i = 0; i < arr1.length; i++) {
console.log(`arr1[${i}]:`, arr1[i]);
}
}
console.log("students:", students);
console.log("students has .forEach2 function ?", typeof students.forEach2 == "function");
console.log("forEach2 is a function?", typeof forEach2 == "function");
console.log("forEach2(arr1)...");
forEach2(students);
console.log("students.forEach(student)...");
//forEach already has a native implementation
students.forEach((student)=> {
return console.log("student:", student);
});
JavaScript is an object-oriented language with prototypal inheritance.
Object-oriented means you have objects with members (called properties in JavaScript) which hold values. In JavaScript, functions are “first-class citizens”, meaning you can assign them to variables just like you would other values.
When you write write a function such as ‘function x(y) { return y +1; }’, what’s really happening is 1) you are declaring a variable named “x”, and 2) you are creating a function “value” which is then assigned to that variable. If you have access to that variable (it’s within scope), you can invoke the function like ‘x(5)’. This evaluates to a new value which you could assign to another variable, and so on.
Ok, so now we have a problem. If functions are values, and values take up space (memory), then what happens when you need a bunch of objects with the same function? That’s where prototypal inheritance comes in. When we try to access a value on an object, via either the member access operator ‘.’, like ‘myObj.someValue’, or via an indexing operator ‘[]’ like ‘myObj[“someValue”] (both of which are equivalent in JavaScript, for the most part), the following occurs:
The runtime checks to see if a ‘myObj’ variable exists in the current scope. If it doesn’t? Exception!
The runtime looks at the object referenced by the variable and checks to see if it has a property with the key “someValue”.
If the object has that property, the member access expression (‘myObj.someValue’) evaluates to that property’s value, and we’re done.
If the object does not have that property, we start doing prototypal inheritance stuff. In JavaScript, all this means is that when we try to access a property that doesn’t exist, the runtime says “hey, what if this objects *prototype has a property with that key?” If it does, we use the prototype’s property’s value. If it doesn’t, we return ‘undefined’.
Notice that because prototypes are just objects, and therefore can themselves have a prototype, step 4 is recursive until we run out of prototypes on which to attempt member access.
Ok, so at this point you may be thinking “what’s a prototype and what does it have to do with my question?” It’s just an object. If any object has a property with the key “prototype”, then that property’s value IS a prototype. Specifically, it’s that object’s prototype. And so this is where your problem arises.
There is no property on your object with the key “forEach2”. Why? Because you didn’t put it there, and you didn’t put it on the object’s prototype (or any of the prototypes “up stream”.
The ‘forEach’ function of an Array exists as a property on the Array’s prototype: ‘Array.prototype.forEach = function (...) {...}’. Your function does not, and therefore you cannot use member access on an array to get that value (the function), and that’s why your code is borked.
Fortunately for you, a variable ‘forEach2’ exists in your current scope, and you can just use it without needing to do any member access! You just write ‘forEach2(students);’ and that’s all.
But what if you want to access that function anywhere you have an array? You have two options: put it on every instance of your arrays, or put it on Array’s prototype. ‘Array.prototype.forEach2 = forEach2;’ however, if you do this you will need to change your function a bit. Right now it expects the array as its first argument (‘arr1’), but its redundant to write ‘students.forEach2(students)’ because when a function is invoked immediately following member access, the function will be provided with a special variable ‘this’ which will have the value of the object for which you are accessing its member. So, in this case, you would omit the ‘arr1’ argument and instead just use the the special ‘this’ variable which is magically in scope within your function.
Array.prototype.forEach2 = function ()
{
for (var i = 0; i < this.length; i++)
{
console.log(this[i]);
}
}
I hope this clarifies some things for you, and I hope it raises a bunch more questions.
P.S: Adding things to prototypes is both powerful and considered harmful unless you know what you’re doing and have a good reason to do it (like writing polyfills)... so do it at your own peril and use responsibly.
For your example to work, simply add the following statement after definition of forEach2:
// Here you're redefining the built-in forEach function with your
// custom function
students.forEach = forEach2;
// Now this must work
students.forEach(students);
This is an explanation why is that:
An array is a particular implementation of the Object. Object is an aggregate of the property:value pairs, such as
{'some_property': '1',
'some_function': function(),
'forEach': function() {<function logic>},
...
}
Your error 'Uncaught TypeError: students.forEach2 is not a function' tells, that there is no property forEach2 (which supposed to be a function) in between the Object's properties. So, there are two methods to correct this situation: - add a property (method function) to the object, or alter the existing property with similar functionality (not necessarily though).
[1] The first method assumes you add a new property function using Array.prototype.forEach2 = function() {...}.
[2] The second - you may redefine or alter any property in the Object by just assigning a new value to that property: Object.forEach = forEach2
Because the function forEach2 is not available either within the Array.prototype or is not a direct property of that array, so, you have two alternatives to use that custom forEach:
Use a decorator to add that function to a specific array
var students = ['foo', 'bar', 'baz'];
function forEach2() {
for (i = 0; i < this.length; i++) {
console.log(this[i]);
}
}
function decorate(arr) {
arr['forEach2'] = forEach2;
return arr;
}
decorate(students).forEach2()
Add that function to the Array.prototype
var students = ['foo', 'bar', 'baz'];
Array.prototype.forEach2 = function() {
for (i = 0; i < this.length; i++) {
console.log(this[i]);
}
}
students.forEach2();
Both alternatives use the context this to get the current array.

Defining a nested object property in Javascript [duplicate]

This question already has answers here:
Javascript: how to dynamically create nested objects using object names given by an array
(25 answers)
Closed 6 years ago.
I need to send a JSON object to a server which requires that the properties
are nested. For example, the data object may be nested 2 levels deep. However, one cannot simply declare the object directly:
var foo = {};
foo.bar.bartwo = "data"; //Uncaught TypeError
I am currently attempting to bypass this by manually creating the nested object layer.
var foo = {};
foo.bar = {};
foo.bar.bartwo = "data"; //Successful
However, this can quickly get out of hand if the object requires multiple levels of nesting.
Is there a better method in Javascript or Jquery to handle this issue (which does not work by simply golfing the second code example)?
Clarification: The solution should be able to allow for direct access to nested properties, without necessitating that all of the intermediate properties also be created.
without defining nested object i.e foo.bar = {};
you can not use or assign value to it
javascript object must be defined first to use it
otherwise it will give you 'undefined' error i.e foo.bar is undefined
create a small method that does this
function nested(x, y){
nestedA="";
parts = x.split('.');
for(i=0; i<parts.length; i++) {
nestedA += parts[i];
eval(nestedA + ' = {}');
nestedA += '.';
}
eval(nestedA.slice(0,-1)+ '= "'+y+'"');
}
nested('foo.bar.bartwo', "data");

Access property within javascript object [duplicate]

This question already has answers here:
Get property of object in JavaScript
(3 answers)
Closed 6 years ago.
I am trying to access a property within an object and return it.
Note the name of the object can change, so accessing it using title_can_change.property will not work.
Take the following object:
{
"title_can_change":{
property: 1
}
}
How do I return the value of 'property'?
MORE INFO:
This object is being returned from a search which contains an array of results from several API's. This object is returned to detail the API the result has come from (the search goes through several API's).
So this would be more like:
apiData:{
"apiName":{
price: 500
}
}
"apiName" is not fixed and changes to say the name of the API. So it cannot be referenced by "apiName' in any of the code.
You could create a function to return the value of the property of whatever object you pass to it:
var getProperty = function(obj) {
return obj.property;
};
If you have an object and you want to access it's first key's value you can go with something like this (dirty example):
var myObj = {
"title_can_change"{
property: 1
}
}
myObj[Object.keys(myObj)[0]];
I home this helps.
So I think I know what you are wanting and here is a low-level solution that may prove valuable and show you some neat things about the language.
https://jsfiddle.net/s10pg3sh/1/
function CLASS(property) {
// Set the property on the class
this.property = property || null;
}
// Add a getter for that property to the prototype
CLASS.prototype.getProperty = function() {
return this['property'];
}
var obj = new CLASS(9);
alert(obj.getProperty());
What you are doing in the above is creating a "class" for your new variable. When you create your object with the new keyword as show you still get your normal JS object (everything is an object anyways), but you get the convenience of the getProperty method. This being on the prototype insures that any new CLASS variables you create will have that method. You can change the variable names and you will always have access to that property by having access to the instance (variable). This is a very common OO paradigm and is the strength of a prototypical language so while it may be over the top for your needs I figured I would add it as an answer here...
If this object is global, then you can use window['title_can_change']['property']. If it's just another property of another object (called another_one) you can access it with another_one['title_can_change']['property'].
Furthermore: You can have a variable (let's call it title_name) to ease the call:
....
var title_name = "title_can_change";
var myObj = window[title_name]['property'];
title_name = "title_has_changed";
var anotherObj = window[title_name]['property'];
.....
OR
....
var title_name = "title_can_change";
var myObj = another_one[title_name]['property'];
title_name = "title_has_changed";
var anotherObj = another_one[title_name]['property'];
.....
Kind of a guess here since the question is still somewhat unclear. I am assuming that you want to iterate over an objects properties whose names are unknown.
This might be a solution.
for (var property in object) {
if (object.hasOwnProperty(property)) {
// check objects properties for existence
// do whatever you want to do
}
}
Use for...in to iterate over the keys of the object and check if your inner object contains your property
var o = {
"title_can_change":{
property: 1
}
};
for (var k in o) {
if (o.hasOwnProperty(k) && o[k].property) {
return o[k].property;
}
}

Objects in Javascript Arrays Mysteriously Linked Together

I have the following code.When I access w[1][0], I want only the object at that one location to be changed. However, all the objects change instead. I'm assuming this is because at some level, they are all pointing to the same object. How would I fix this?
var createArray = function(dim,init){//takes an array of dimensions and the initial value of each element
if(dim.length > 0){
var x = new Array();
for(var i = 0; i < dim[0]; i++)
x[i] = createArray(dim.slice(1),init)
return x;
}
return init;
}
var w = createArray([2,2],{top: false,left: false});
console.log(w);
w[1][0].left = true;
console.log(w);
In JavaScript, objects are passed by a reference, not by value. That means that if you pass the same object to a few variables, they all point to the same place in memory. This is why your init object is being changed everywhere.
To prevent this, you need to clone the object before assigning it to your variables. One of the simplest built-in methods is to use JSON, like this:
var copy = JSON.parse(JSON.stringify(original));
So in your case that would be it:
x[i] = createArray(dim.slice(1), JSON.parse(JSON.stringify(init)));
w[1][0].left = true;
This line is changing the only instance of the object. See, this line:
var w = createArray([2,2],{top: false,left: false});
is the only line in your code that creates a new object (of the type you're interested in) via the {} literal there. All other set operations (newVar = init) only copy a reference to that same object.
That sounds annoying, but it has a lot of good uses in code. To fix it, you'll want to create a copy each time, to replace the final line of createArray
var myCopy = {};
for (var key in origObject) {
if (origObject.hasOwnProperty(key)) {
myCopy[key] = origObject[key];
}
}
return myCopy;
Be warned - this is a "shallow copy", so it will only copy the top-level properties, and any objects a level deep will still be references. Many JavaScript libraries have functions to create deep copies for you.

Categories

Resources