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)
Related
So I was playing around the other day just to see exactly how mass assignment works in JavaScript.
First I tried this example in the console:
a = b = {};
a.foo = 'bar';
console.log(b.foo);
The result was "bar" being displayed in an alert. That is fair enough, a and b are really just aliases to the same object. Then I thought, how could I make this example simpler.
a = b = 'foo';
a = 'bar';
console.log(b);
That is pretty much the same thing, isn't it? Well this time, it returns foo not bar as I would expect from the behaviour of the first example.
Why does this happen?
N.B. This example could be simplified even more with the following code:
a = {};
b = a;
a.foo = 'bar';
console.log(b.foo);
a = 'foo';
b = a;
a = 'bar';
console.log(b);
(I suspect that JavaScript treats primitives such as strings and integers differently to hashes. Hashes return a pointer while "core" primitives return a copy of themselves)
In the first example, you are setting a property of an existing object. In the second example, you are assigning a brand new object.
a = b = {};
a and b are now pointers to the same object. So when you do:
a.foo = 'bar';
It sets b.foo as well since a and b point to the same object.
However!
If you do this instead:
a = 'bar';
you are saying that a points to a different object now. This has no effect on what a pointed to before.
In JavaScript, assigning a variable and assigning a property are 2 different operations. It's best to think of variables as pointers to objects, and when you assign directly to a variable, you are not modifying any objects, merely repointing your variable to a different object.
But assigning a property, like a.foo, will modify the object that a points to. This, of course, also modifies all other references that point to this object simply because they all point to the same object.
Your question has already been satisfyingly answered by Squeegy - it has nothing to do with objects vs. primitives, but with reassignment of variables vs. setting properties in the same referenced object.
There seems to be a lot of confusion about JavaScript types in the answers and comments, so here's a small introduction to JavaScript's type system:
In JavaScript, there are two fundamentally different kinds of values: primitives and objects (and there is no thing like a 'hash').
Strings, numbers and booleans as well as null and undefined are primitives, objects are everything which can have properties. Even arrays and functions are regular objects and therefore can hold arbitrary properties. They just differ in the internal [[Class]] property (functions additionally have a property called [[Call]] and [[Construct]], but hey, that's details).
The reason that primitive values may behave like objects is because of autoboxing, but the primitives themselves can't hold any properties.
Here is an example:
var a = 'quux';
a.foo = 'bar';
document.writeln(a.foo);
This will output undefined: a holds a primitive value, which gets promoted to an object when assigning the property foo. But this new object is immediately discarded, so the value of foo is lost.
Think of it like this:
var a = 'quux';
new String(a).foo = 'bar'; // we never save this new object anywhere!
document.writeln(new String(a).foo); // a completly new object gets created
You're more or less correct except that what you're referring to as a "hash" is actually just shorthand syntax for an Object.
In the first example, a and b both refer to the same object. In the second example, you change a to refer to something else.
here is my version of the answer:
obj = {a:"hello",b:"goodbye"}
x = obj
x.a = "bonjour"
// now obj.a is equal to "bonjour"
// because x has the same reference in memory as obj
// but if I write:
x = {}
x.a = obj.a
x.b = obj.b
x.a = "bonjour"
// now x = {a:"bonjour", b:"goodbye"} and obj = {a:"hello", b:"goodbye"}
// because x points to another place in the memory
You are setting a to point to a new string object, while b keeps pointing to the old string object.
In the first case you change some property of the object contained in the variable, in the second case you assign a new value to the variable. That are fundamentally different things. The variables a and b are not somehow magically linked by the first assignment, they just contain the same object. That's also the case in the second example, until you assign a new value to the b variable.
The difference is between simple types and objects.
Anything that's an object (like an array or a function) is passed by reference.
Anything that's a simple type (like a string or a number) is copied.
I always have a copyArray function handy so I can be sure I'm not creating a bunch of aliases to the same array.
I have an empty object myscroll defined as var myscroll = {}. Now I want to add an array property to it. I did it as follows:
var myscroll = {}
myscroll.point[0] = getScrollpos("home");
myscroll.point[1] = getScrollpos("artists");
myscroll.point[2] = getScrollpos("songs");
myscroll.point[3] = getScrollpos("beats");
myscroll.point[4] = getScrollpos("contact");
I get the error myscroll.point is not defined. Then I first defined it as myscroll.point = [];, then the code worked.
So, Why can't we directly set array values and add that property to an object in javascript? Why do we have to define it first independently?
When you are dealing with object properties, by default you can access any object property and value of that property would be undefined if it wasn't set before. So, by accessing not defined property with index (myscroll.point[0]) you are trying to access property 0 of undefined, which is primitive value in javascript and has no properties, so you are getting TypeError.
As result you can set primitive values to not defined object property, but cannot dial with not defined prop as with object.
Also wanna to point you and explain situation with a little bit similar from first view situations in code below:
var obj = []
obj[0] = 10
notDefinedObj[0] = 10 // cause ReferenceError
Array is object. In JS you can't modify/add/delete object properties without initialising object before.
That's caused because objects are stored in memory and you can access them by reference. When you attempt to add new property to it, for instance add new element to list, you are trying to attach property to variable which has no Reference, that's why you are getting ReferenceError.
Good Luck!
With myscroll.point you're trying to access a point property on the myscroll object. But there is no such property on that object. That's why you're getting a undefined is not an object error message (or something similar - depending on your browser).
If you're coming from PHP, this might be strange but actually it's much more explicit than the magic involved in the following php snippet for example:
$myscroll = [];
$myscroll['point'][0] = getScrollpos("home");
// ...
PHP automagically created sub arrays for keys that do not exist.
Update after comment
There is a significant difference between myscroll.mypoint = 5; and myscroll.point[0] = getScrollpos("home");.
In the first case your setting the point property on myscroll to 5 explicitly. But in the second case you're trying to access the [] operator (which is an array operator) on a non-existing property point. Theoretically Javascript could do the same magic as PHP and create the array automagically on the fly, but it doesn't. That's why your getting an error.
It's the same as trying to access a fictitious property myproperty on myscroll.mypoint like myscroll.mypoint.myproperty. This will not work as well, because you're trying to access myproperty on mypoint which is undefined on myscroll.
Because myscroll.point[0] = getScrollpos("home"); can be understood as Get the first element of the point array inside of myscroll and set it to... You can't access the first element of an non-existing array.
Simply check typeof of myscroll array variable and then check the typeof of myscroll.point. You have tried to assign properties of an array, outside of an array. It is empty or undefined.
You are trying to access the point property of myscroll which is not defined (because myscroll = {}).
If you will look at the console with myscroll.point, it will return you undefined. Here you were trying to put something in undefined so you got TypeError: myscroll.point is undefined.
If you define myscroll like this:
var myscroll = {
point : []
}
Then your code will work and you won't need to define myscroll.point = [].
if you have an an empty object and you want to set a new property that holds an array you should do this.
var obj = {};
obj['propertyName'] = [];
this will put a property with corresponding propertyName that holds an array that you can later populate.
if your getScrolloops() returns an array you can do this
obj['propertyName'] = getScrolloops();
Idealy in your case you can do this:
obj['propertyName'] = [getScrollpos("home"),
getScrollpos("atrist"),
getScrollpos("songs"),
getScrollpos("beats"),
getScrollpos("contact")
];
EDIT: Explanation: Why is your code not working?
As explained here:
You can define a property by assigning it a value.
What you do is trying to define a property by assigning a value to an index of that property. This will not work because you are not assigning a value to the property it's self but to index of a property that dose not exist.
Also i need to mention that you can use both property accessors to achieve that. This could be a helpful link.
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.
What is the name of the technique the example uses below to pass a variable to an object in javascript? And furthermore, why is it not working ("large" is not outputted to the console log as expected)?
var thumbnailBlock = new ThumbnailBlock();
thumbnailBlock.thumbnailSize = "large";
function ThumbnailBlock() {
this.thumbnailSize;
console.log("DEBUG");
console.log(this.thumbnailSize);
}
The explanation what is going wrong in your code from Willem Mulder's answer:
There is no specific name. You simply set an object property.
The 'large' is not outputted because you first create an object using the ThumbnailBlock constructur function (where it logs the this.thumbnailSize) and only then set the .thumbnailSize to "large".
You could pass the size as function argument.
function ThumbnailBlock(size) {
this.thumbnailSize = size;
}
var thumbnailBlock = new ThumbnailBlock("large");
console.log(thumbnailBlock.thumbnailSize);
Also, have a look at the The Constructor Pattern and other nice patterns on that page. I also recommend the chapter on OOP in the free book Eloquent JavaScript.
There is no specific name. You simply set an object property.
The 'large' is not outputted because you first create an object using the ThumbnailBlock constructur function (where it logs the this.thumbnailSize) and only then set the .thumbnailSize to "large".
The proper answers are already given, I just want to point out for the record that adding dynamic property won't work if your object is sealed or frozen.
function ThumbnailBlock(size) {
Object.seal(this);
}
var thumbnailBlock = new ThumbnailBlock("large");
thumbnailBlock.thumbnailSize = 10;
console.log(thumbnailBlock.thumbnailSize); // undefined
In strict mode you will raise an exception instead.
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.