Why do variables in object-nested array not change? - javascript

function Dealership = function(){
this.car1="Honda";
this.car2="Chevy";
this.car3="Toyota";
this.carList=[this.car1,this.car2,this.car3];
};
var tomsauto = new Dealership();
tomsauto.car2="Subaru";
console.log(tomsauto.carList); //returns honda chevy toyota
I'm confused as to how the array is processed. Is it static, holding only the variable values it had at instantiation, or should "this.car1" change when I change tom.car1?

When you create the array via that array instantiation expression, the runtime system copies the values of each of those object properties into the array. If you later change the values of the properties, they'll change independently of the array elements.
There's no way in JavaScript to make a property of one object "mirror" the property of another. (Well, no intrinsic way; you can write code to do it.)

As Teemu said: your carList is populated with values, not references.
An easy workaround is to change it to a function getCarList:
var Dealership = function () {
this.car1 = "Honda";
this.car2 = "Chevy";
this.car3 = "Toyota";
this.getCarList = function() {
return [this.car1, this.car2, this.car3];
}
};
var tomsauto = new Dealership();
tomsauto.car2 = "Subaru";
console.log(tomsauto.getCarList());

I think you are running into that problem because of how closures work in JavaScript.
When you declare the function as you did, the value of car1, car2, car3 get evaluated in that scope and then are assigned to the array.
When you do the new Dealership() bit, the values of that array are pretty much set as they were when the function was evaluated. After you do
tomsauto.car2 = "Subaru";
the value of car2 will change, but the array will not because the values are not being re-evaluated.
If you want to know more about how and why, I suggest you read more about closures in javascript and functional languages in general.

Related

What is the difference between Javascript Object, Property and Variable, are they all the same?

What is the difference between a JS:
Object, Property and Variable ?
Sorry I'm new to JavaScript but from the way I'm understanding it is a Variable is a container to store information/data types yes ?
An object is a variable but with several different properties (whereas with a variable you have one property)? name:value pairs
a property is the building blocks of objects? is that what makes an Object an Object? because it is a variable with several name:value pairs? ........
I'm supper confused!!! are all three the same are they like interchangeable?
the only example I can think of is
Human body:
Cells
Tissues
Organs
-organs are made up of tissues
-tissues are made up of cells
-cells are tissues, basically lots of cells make up tissues and lots of tissues make up organs.
So basically organs are also cells but they are made up of a lot of cells?
I'm a bit dumb and slow when it comes to learning can somebody please enlighten me?
Explain the differences between them in very simple basic language like your explaining it to a 10 year old or something please
answers much appreciated,
Thanks :)
ps There may be a part 2 to this question
the way I'm understanding it is a Variable is a container to store information/data types yes ?
Almost. A variable is a container that stores a value. Each value is of a specific data type. Common types are number, string and Boolean.
Example:
var userID = 42;
userID is a variable. It contains the value 42. 42 is a number value, i.e. it is of type number.
A JavaScript object is a value of type object. Objects are not just simple, scalar values, they are "container" values. They can themselves contain multiple different values.
Essentially objects are key-value stores, i.e. they contain one or more keys associated with a value. These key-value pairs are called properties.
Example:
var record = {
name: 'Paul',
age: 42
};
record is a variable. It contains an object as value. The object has two properties, name and age. name holds a string value, age a number value.
When one refers to 'variable' one typically imagine a container with some memory to hold a value.
Objects are variables too but dynamically transform to containers of primitives or more-complex values upon Assignment! Complex values can be objects that hold primitive data types or even other objects such in the example below :
var SNOCounter; //gives undefined ^
SNOCounter = 3;
AccObjVar = {firstName:"John", lastName:"Smith"}; //creates an JS "object" variable with two "properties" that hold 'string' type values
AccountWrapperObj = {SNO:SNOCounter,AccountName:AccObjVar};
The dynamism of object properties is such that although AccountWrapperObj which is a JS Object holds a primitive value and Object as its original value. Replacing the AccountName property with an integer can be done by just assigning it the integer value (the properties have dynamic data types just like variables in Javascript)
AccountWrapperObj.AccountName= 'Albert Einstein'; // changes the type of AccountName from AccObjVar object type to a String
----------Extra Info ---------------
^ I am not quite clear on the memory assignment part at this stage. Link says there needs to be a bare minimum memory here for referencing the variable and actually assigning it a value.
Does declaring a variable in JavaScript with var without assignment consume memory?
A variable is a binding to a value in memory and not an object.
The item in a box analogy isn’t quite right. I think that it’s more along the lines of two tin cans connected by a string, one can being the reference(variable) and the other being the value.
I'm also new to JS, so I'll tell what's helping me here
one thing that's helping me is to think about variables as 'labels', something temporary related to execution (a metaphor from Luciano Ramalho's Fluent Python book...), and not as 'boxes', a metaphor that I've seen in a lot of tutorials
so variables are temporary, and related to execution of some function, or of the whole script (depending of where they're declared... see the difference of var, let and const for more about this)
properties, on the other hand, are related to objects, attached to the obj while it or the property exists; so you cannot create a property that's not related to an obj
let myObj = {}; // 'myObj' is the 'label' of the obj we're creating
myObj.prop = true; // we create 'prop', a property of 'myObj', using the dot notation
almost everything in JS is an obj, and objs are custom types/structures for data; functions are also objects, but they're a 'special' kind of obj, we can create and return objects with them (we can execute functions to create/return objs); so
let foo; // declaring an empty variable; the word let is related to the scope of the variable, you can use var, let or const when declaring variables
foo = function(){ return {}; }; // foo returns an empty obj
myObj = foo(); // we execute foo() so that myObj is again an empty obj
the value of a property can also be an object, so we can also do
myObj.foo = function(...args){ // receives no or more arguments
const createProps = (el, i) => { // declares a variable and defines an arrow function
this[`prop${i+1}`] = el; // uses the index of the argument to create the name of the property, with the argument value
}
args.forEach(createProps); // for each arg, create a property
}
myObj.foo('some', 'new', 'properties'); // execute the function, creating new properties in 'myObj'
above, the function that creates properties for my myObj is part of myObj, as a property...
so objects and properties have to do with data structuring, how I relate the different kinds of data in my code; and functions and variables - these 'temporary labels' - have to do with execution, doin' stuff, creating objs, and so on... both 'portions' workin' together, of course

Accessing value of key inside object

There's a handful of questions extremely similar to this, I know, but I can't seem to get anything to work.
For sake of brevity, I'll summarize this. I have this constructor function with strings assigned as values of the keys (assignment).
var Quote = function() {
this.quote1 = 'You can discover more about a person in an hour of play than in a year of conversation.';
this.quote2 = 'Nothing is at last sacred but the integrity of your own mind.';
this.quote3 = 'We have to fight them daily, like fleas, those many small worries about the morrow, for they sap our energies.';
this.quote4 = 'Ethics are so annoying. I avoid them on principle.';
this.quote5 = "Never trust anything that can think for itself if you can't see where it keeps its brain.";
};
module.exports = Quote;
Using AJAX I am printing the value of the keys inside the constructor to a static page. However... I am only successful in printing "quote1", "quote2", etc... (Just the name of the keys).
This is what my function for accessing the constructor looks like. My question is: How can I access the string values assigned to the keys inside the constructor? Is that possible?
Thank you in advance.
module.exports = function(object) {
var propArray = Object.keys(object);
var randomProp = propArray[Math.floor(Math.random() * propArray.length)];
return {quote: randomProp};
};
Inside your function, you should be able to access the quote by key using this:
object[randomProp]
In JavaScript, object properties can be accessed using square bracket notation. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects.
As you might have expected, there are several things wrong with your code :)
I've rewritten it with pretty thorough comments.
<script>
// create your 'Quote' class, which can be instantiated as many times as necessary
var Quote = function() {
this.quote1 = 'You can discover more about a person in an hour of play than in a year of conversation.';
this.quote2 = 'Nothing is at last sacred but the integrity of your own mind.';
this.quote3 = 'We have to fight them daily, like fleas, those many small worries about the morrow, for they sap our energies.';
this.quote4 = 'Ethics are so annoying. I avoid them on principle.';
this.quote5 = "Never trust anything that can think for itself if you can't see where it keeps its brain.";
};
// now let's set up the 'exports' method on the function's prototype
// this will allow any new instance of the Quote function to call or override this method
// without affecting the master 'Quote' class
Quote.prototype.exports = function() {
// you don't need to explicitly pass an object to this function
// just have it reference itself using the 'this' keyword
var propArray = Object.keys(this);
var randomProp = propArray[Math.floor(Math.random() * propArray.length)];
// objects in JavaScript can be handled like associative arrays
// simply access the key of 'this' with the value provided by 'randomProp'
return {quote: this[randomProp]};
};
// create a new instance of 'Quote'
// this guy can be used and manipulated independent of the master 'Quote' class
var module = new Quote();
// let's store the value returned by 'exports' in randomQuote
// note the () at the end of module.exports -- this tells JavaScript to treat the object as a function
var randomQuote = module.exports();
// write your quote to the document -- or do whatever else you want to with it at this point
document.write(randomQuote.quote);
</script>
Instead of return { quote: randomProp } you should use return object[randomProp].
You can access object properties via dot notation or square bracket notation.
Here's an example from jsbin
https://jsbin.com/yopeli/edit?js,console

Renaming Array with Variable

One of the problems with teaching yourself how to code is that you miss some things that might be fairly simple:
I have written a function which takes text files (e.g. "someData1.txt", "someData2.txt" etc.) turns their contents into an array ("myArray"), and extracts their title as a variable ("fileName").
I am at the stage where I have parsed the filenames and the arrays, but I would like to rename each array with the variable, so that the first array becomes "someData1", and so on. I already have a bunch of code which will do various things with each different array, so it would useful if I could name them the way I wish.
I thought I could use valueOf to do it, as in
fileName.valueOf() = myArray;
but that does not work. So how do I do this?
Thanks!
Probably the easiest way would be to use an object and then use array notation to assign keys to it. Let me show you:
var myObj = {};
myObj.someProperty = 1;
is the same as
myObj['someProperty'] = 1; // note the quotes
So, that makes possible to use variable names as keys. In your example:
var fileName = 'someData1';
var myObj = {};
myObj[fileName] = myArray; // myArray being file contents from your example
and now when you want to access the contents, you can simply do:
myObj.someData1
or:
myObj['someData1']
Just make sure you have no duplicate file names and you're good to go.
What you want to do is defining a variable name dynamically.
It is not possible in Javascript though, but you can be tricky.
You have then two options :
Use the global scope object to store your variables (not a good practice) :
global[variableName] = array;
And then you will be able to access it in the scope :
global['toto'] = 42;
console.log(toto);
=> 42
This is NOT a good practice but is the only way to define a variable in the scope dynamically.
Use an object to store it :
var myArrays = [];
myArrays[variableName] = array;
In each case you define in fact a property of an object.
You have to keep in mind that :
myArrays['toto'] = 42;
is the same that :
myArrays.toto = 42;
So to access your array, just do :
myArrays.toto

Using JSON to create instances of an object

I'm trying to learn to program. I've gone through a list of tutorials sites online and I'm stuck on a thing that I think is extremely important for me to understand.
My questions:
(This is what I'd like to understand most) In my for...in loop, why is creating new "obj" objects using the "Contacts" constructor working? It seems like I would need a different name each time I loop so that I don't overwrite the object that I've created the pass before. If this is correct, how do I do this if I don't know anything about the number or value of contacts ahead of time? Additionally, why does the title of the any of the objects in the console logs not say obj? Am I confused about what it means to create an instance of an object? Are the names of these instances unimportant?
Why are all of the properties undefined? Should referencing properties from the temporary "i" variable work?
Creating objects from an unknown total of data entries seems really important. Unfortunately, places like Codecademy fall short here. You always manually create new instances of objects with hardcoded names they give you. But what would happen if there were two of the same name?
Thanks so much for any help I may get on this. Don't hold back from telling me anything else silly that I may be doing.
Here is a link to a console screenshot - http://i.imgur.com/TK4dtfV.png
var TestApp = {};
// my data... taken from wherever
TestApp.jsonContacts = {
contact1: {
name: "Ethan",
age: 24
},
contact2: {
name: "Evan",
age: 30
},
contact3: {
name: "Paul",
age: 9000
}
};
// I know this is silly, just let me pretend...
TestApp.jsonStrung = JSON.stringify(TestApp.jsonContacts);
TestApp.globalContactList = [];
// my constructor function to create instances of Contact
TestApp.Contact = function(name, age){
this.name = name;
this.age = age;
TestApp.globalContactList.push(this);
};
// where I'm taking data and creating new Contact objects
TestApp.instantiateObjects = function(){
// I know this is silly, just let me pretend...
var jsonUnstrung = JSON.parse(TestApp.jsonStrung);
// I think I'm looping through the first set of objects sitting in jsonContacts
for (var i in jsonUnstrung) {
var obj = new TestApp.Contact(i.name, i.age);
console.log(obj);
}
console.log(TestApp.globalContactList);
};
TestApp.instantiateObjects();
In my for...in loop, why is creating new "obj" objects using the "Contacts" constructor working?
A variable is just a holding place for a value. It is not the value itself. If you overwrite a variable with a new value, the previous value it held will continue to exist as long as something is holding a reference to it; it's simply that the variable won't be referring to it anymore.
It seems like I would need a different name each time I loop so that I don't overwrite the object that I've created the pass before.
No, you don't. One variable is fine, as long as you do something with the value before you assign the variable to the next value.
If this is correct, how do I do this if I don't know anything about the number or value of contacts ahead of time?
It doesn't matter how many you have.
Additionally, why does the title of the any of the objects in the console logs not say obj?
console.log() prints out the value that is passed to it. It doesn't care (doesn't know) anything about the variable that you pass to it.
Am I confused about what it means to create an instance of an object?
It seems so. Creating an instance of an object allocates some memory to store that object's values. A variable allows you to gain access to that allocated object.
Are the names of these instances unimportant?
Yes, object instances don't have names.
Why are all of the properties undefined?
i holds the property names of the object you are iterating through, so in this case, the strings "contact1", "contact2", "contact3". These strings don't have a name or age property, so your constructor is receiving two undefined values.
Should referencing properties from the temporary "i" variable work?
You need to use i as a property name to access the property values:
var obj = new TestApp.Contact(jsonUnstrung[i].name, jsonUnstrung[i].age);
In general, it's a good idea not to have side-effects like TestApp.globalContactList.push(this); in a constructor. There may be cases where doing so makes sense, but most of the time, removing that line and doing this would be preferable:
for (var i in jsonUnstrung) {
var contact = jsonUnstrung[i];
var obj = new TestApp.Contact(contact.name, contact.age);
console.log(obj);
TestApp.globalContactList.push(obj);
}

Question about Javascript pointer to an object property

I wanted to set a variable to point to property in an newly created object to save a "lookup" as shown in the example below. Basically, I thought the variable is a reference to the object's property. This is not the case; it looks like the variable holds the value. The first console.log is 1 (which is the value I want to assign to photoGalleryMod.slide) but when looking at photoGalleryMod.slide, it's still 0.
Is there a way to do this? Thanks.
(function() {
var instance;
PhotoGalleryModule = function PhotoGalleryModule() {
if (instance) {
return instance;
}
instance = this;
/* Properties */
this.slide = 0;
};
}());
window.photoGalleryMod = new PhotoGalleryModule();
/* Tried to set a variable so I could use test, instead of writing photoGalleryMod.slide all the time plus it saves a lookup */
var test = photoGalleryMod.slide;
test = test + 1;
console.log(test);
console.log(photoGalleryMod.slide);
Yes, you're making a copy of the value, because "slide" is set to a primitive type. Try this:
this.slide = [0];
and then
var test = photoGalleryMod.slide;
test[0] = test[0] + 1;
then change the logging:
console.log(test[0]);
console.log(photoGalleryMod.slide[0]);
In that case you'll see that you do have a reference to the same object. Unlike some other languages (C++) there's no way to say, "Please give me an alias for this variable" in JavaScript.
it looks like the variable holds the value
That's correct. Since you're using number primitives, variables contain the value rather than pointing to it. Variables only contain references when they're referring to objects.
The way to do it is to use an object property and to point to the object — which is exactly what you have with photoGalleryMod and its slide property.

Categories

Resources