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.
Related
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;
}
}
I was trying to understand some javascript and found some quite unexpected behavior. Not knowing much about this language I wanted to find out what this behavior is called so that I can read about it formally.
Here's an example of the behavior:
var test={'x':2};
var test2=test;
test2.sourceLinks = [];
console.log('test',test);
console.log('test2',test2);
To my amazement, I found that modifying the 2nd variable somehow modifies the first as well. The variable "test" will also have an attribute .sourceLinks = []. Do I understand what's happening correctly, and if so, what's the formal term for this behavior?
I found that the answer to this is covered in How do I correctly clone a JavaScript object? after I posted it, although that covered more than I was asking about.
Behavior is called creating a reference. When variable assigned is an object actually it is not copied, rather the result of assignment is a new reference (pointer) to the object.
This doesn't happen with primitive types:
number,
string,
boolean,
null,
undefined.
But happens with all object types:
object,
Array,
function.
This difference is significant in javascript. When some value should be passed to another scope and it might be modified there it should be passed be reference.
function main(){
var x = 1;
modify(x);
console.log(x);//x remains 1
}
function modify(arg){
arg = 10;
}
Whereas when it is passed as a field of an object, it can be modified via reference to an object:
function main(){
var o = {x : 1};
modifyObj(o);
console.log(o);//o.x now equals 10
}
function modifyObj(arg){
arg.x = 10;
}
It's holding the reference.
When you assign object/array/function to another object/array/function it'll assign reference instead of value.
To overcome this you have to clone it
When declaring a variable in Javascript you are creating an object in memory and the variable in the scope is a pointer to that memory object.
In your example both variables (test and test2) are pointing to the same object. Hence, when you modify the the either variable pointer, it is modifying the same object in memory.
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.
I just can't understand how variables are passed, why are some passed by reference while other by value?
Example:
var a=4;
var b=a;
b=b++;
alert(a);//unmodified 4
var c=["t","ttt"];
var d=c;
d=d.sort(function(x,y){return (y.length-x.length);});
alert(c);//modified ["ttt","t"]
Where can I find a list of what variables will work like the first example and which like the second? (booleans, strings, etc... there are too many to test them all by miself)
JavaScript is always pass by value.
It's very common to say that objects in JavaScript are pass by reference, however that is not true. In a true pass by reference language, you could pass a reference to an object's reference, and have it point to another object. This is not possible in JavaScript.
Take, for example, C#. By default everything in C# is pass by value, just like JavaScript.
void foo(string s) {
s = "passbyvalue";
}
string a = "original value";
foo(a);
// a is still "original value"
However, if you alter foo to use pass by reference, the behavior changes:
void foo(ref string s) {
s = "passbyreference";
}
string a = "original value";
foo(ref a);
// a is now "passbyreference"
In JavaScript, only the first example is possible.
In JavaScript, everything is pass by value. This includes the object reference (yes, it is confusing). The reference itself is a value (it's very much like a pointer). It merely contains an id that allows the runtime to look up the object that is most likely stored in its heap. When you pass an object to a function, you are actually copying its reference into the function
It may be a seemingly small, and even anal, difference. But it's a key difference. Languages that have true pass by reference such as C# and C++ allow you to do things that are simply not possible in languages like JavaScript. The above trite example is one.
Imagine everything in JavaScript as an object. Object references are copied by value, but object properties are still used by reference. So:
var a = {};
var b = a;
b = 'Blah';
console.log(a); // Still {}
and
var a = {};
var b = a;
b.test = 'Blah';
console.log(a); // Is now {test: 'Blah'}
To simplify things a little: properties are by reference, values are by value.
Usually you can check the method on MDN. For example, the sort method's documentation states (emphasis added):
Sorts the elements of an array in place and returns the array.
The "in place" there says it will modify the array.
All primitives (for example, numbers and booleans) are passed by value; all objects are passed by reference, although some (like String objects) are immutable (although still passed by reference).
All objects get passed by reference and values by value. (technically this is not true, but it explains the behaviour)
Is there a way to get the exact name of the object that this is referring to and not just object Object?
No there is not. An object in javascript doesn't inherently have a name. Instead it has a set of named references which point to it (or possibly none). The this value is just one of these references.
// The {} is an object without a name. Here 'x' is a reference
// to that object
var x = {};
// Now 'y' refers to the same object as 'x'. But neither 'x'
// nor 'y' is the name of the object.
var y = x;
No, but you can see what this is at any given time by dumping to the console:
console.log(this);
You could try something like this, even though it will not work in some cases:
function R3S (){
this.a = function(){
whoIs(this);
}
}
function whoIs(obj) {
console.log(/(\w+)\(/.exec(obj.constructor.toString())[1]);
}
var t = new R3S();
whoIs(t);
t.a();
var l = t;
l.a();
Hope this helps.
Maybe you would want to take a look at this post also : How to get class object's name as a string in Javascript?
"this" is also just another alias to your object, there could be many variable names pointing to the same this as "this" points to. There is no known way to get the original name the object was created with(if any). The best you could get is the type of "this"
Object.prototype.toString.call(this)