Can someone explain what is happening in the code below? I'd expect toString to get called for either both foo and bar, or neither. How is literal object notation different from adding fields to an object after it is created?
function Obj(v) {
this.v = v;
};
Obj.prototype.toString= function() {
window.alert("to string called for " +
this.v);
return this.v.toString();
}
var foo = new Obj('foo');
var bar = new Obj('bar');
// toString is not called here.
var map = {foo : 'blah'};
// toString is called here.
map[bar] = "blah2";
Why do object literals not use toString() while adding to an existing object does use toString()?
http://jsfiddle.net/pByGJ/2/
The main reason that object literals don't evaluate the identifier to the left of the colon is so you're not force to quote all literal names (as you do in JSON).
Bracket notation forces you to quote property names, if you don't, it will be evaluated as a variable.
The reason toString() does get called in the second example is because bar has to be converted to a string to be used as a property name.
In your first example, you're just creating a literal object (that is the exactly the same as {"foo" : 'blah'}). So that is never using the variable foo
If you want to create an object using a variable name, you can't use literal object notation, you have to use [] which is what forces it to call toString()
Here's a function to create objects with variable names in one expression.
function obj(key, value /*, key, value, ... */) {
var obj = {};
for (var i = 0, ln = arguments.length ; i < ln; i+=2) {
obj[arguments[i]] = arguments[i+1];
}
return obj;
}
Clearer Example
The fact that your variable names and values are the same doesn't help understanding the problem. Let me suggest this code
var foo = new Obj('fooValue');
var bar = new Obj('barValue');
var map = {foo : 'blah'};
map[bar] = "blah2";
// You expect map to be {fooValue: 'blah', barValue: 'blah2'}
// But it's {foo: 'blah', barValue: 'blah2'}
To do what you need, use my obj function
// Almost as clear as literal notation ???
var map = obj(
foo, 'blah',
bar, 'blah2'
);
// map = {fooValue: 'blah', barValue: 'blah2'} Yay!!
keys in an object literal are taken as strings, not interpreted as variables. This:
var map = {foo : 'blah'};
is equivalent to this:
var map = {"foo" : 'blah'};
and this:
var map = {};
map["foo"] = "blah";
but is completely different than this:
var map = {};
map[foo] = "blah";
Related
As mentioned in MDN, Property names must be strings.
For code,
var foo = {unique_prop: 1}, obj = {};
obj[foo] = 'value';
console.log(obj[foo]);
In MDN, it says,
In the SpiderMonkey JavaScript engine, this string would be "['object Object']".
How does the property(string literal) of object type obj is stored like?
Is the property stored as "['unique_prop 1']" ?
When you create a property on an object from a variable, JS engine calls toString() method on a passed value. The actual value for the key is decided from its type.
You can check this behaviour yourself:
var foo = {};
foo.toString = function() {
return "toString";
}
var bar = {};
bar[foo] = "prop value";
for (var k in bar) {
console.log(k);
}
Does anyone know what is test[name] mean?
function test(value){
copy(value||{},this);
}
test[name] = function(){
return "test"
}
This will be easiest to explain with an example:
var name = "foo";
test[name] = function(){
return "test"
};
This would add a property named "foo" to the object test, and the value of that property is a function. It doesn't matter in this case that the object test is actually a function, you can assign properties to functions just like any other object in JavaScript.
You could call this function using any of the following methods:
test[name]()
test["foo"]()
test.foo()
Note that test[name]() will not work if the name variable is assigned to something different, for example name = 'bar'.
Javascript has two sets of notation for accessing objects, dot notation (obj.property) and bracket notation (object[property]). More on that at MDN.
test[name] = function (){} assigns an anonymous function to the name property on the the test object (which itself is a function). In this case (as noted by the comments) the variable name is being used to access the property.
This may seem a little strange at first, but it's helpful to remember that in javascript, functions are objects.
All functions in Javascript are also objects. This adds a property to the test function object with a value which is an anonymous function.
For example:
function test(){
return "foo";
}
// test is a function, so it is also an object and
// it can have properties assigned to it
test.x = function(){
return "bar";
};
test(); // "foo"
test.x(); // "bar"
Of course just like with any object you can also use bracket notation:
var name = 'hello';
test[name] = function(){
return "HELLO!";
};
test.hello(); // "HELLO!"
In JavaScript, functions are objects. They have properties. test[name] sets a property (named whatever the name variable holds) to a function.
when you have a javascript object with defined properties you can access the property either with the dot notation obj.property or with the square brackets notation obj[property]
the property could also be a function so if you have an object:
var test = {
foo : function(arg){ console.log(arg) },
bar : 'hello'
};
you can call test.foo('bar') also by doing test['foo']('bar')
This is especially useful in iterations or when you dont know a priori what the name of the property is going to be. For example:
var fun = 'foo';
test[fun]('hello world');
Naturally it's up to you to do proper checks such as
if ('function'==typeof test['foo']){ test['foo']('bar'); }
Also note that you can do checks on the fly like so:
test[ fun || 'foo']('hello');
Taken from the Mozilla page
One can think of an object as an associative array (a.k.a. map, dictionary, hash, lookup table). The keys in this array are the names of object members
There are two ways to access object members: dot notation and bracket notation (a.k.a. subscript operator).
So
test[name] = function (
means: there are (if everything is ok) two objects: test and name (and we know that at least test is present, because you defined it one line before: function test(value))
take the test object (if there isn't a test object an error will happen). Then access the key/value pair with the key calculated from the name object and there put a function.
Now, how the key is calculated from the name object? The same page from before tells us:
Property names must be strings. This means that non-string objects cannot be used as keys in the object. Any non-string object, including a number, is typecasted into a string via the toString method.
Note that the description is a little wrong... test[null] == test["null"] and test[undefined] == test["undefined"], so perhaps the truth is that under the covers something like String(key).valueOf() is done (the String function will convert null to "null" and undefined to "undefined")
Some examples (where => means "is equivalent to, with this values")
var name = 'foo';
test[name] => test['foo']
var name = 123;
test[name] => test['123']
var name = 123.3;
test[name] => test['123.3']
var name = new Date();
test[name] => test['Wed Aug 14 2013 17:35:35 GMT+0200 (...)']
var name = null;
test[name] => test['null']
var name = undefined;
test[name] => test['undefined']
var name = [];
test[name] => test['']
var name = [1,2,3];
test[name] => test['1,2,3']
var name = {};
test[name] => test['object Object']
and so on...
The brackets are how you reference a property via a key into the hash that javascript objects are.
If I have a variable foo that hold a reference to an object:
var foo = someObj;
How can I then use the name of the object as a string?
I tried:
var bar = foo.valueOf()
But that just returned another reference to the object.
What I have is an algorithm that selects from a large number of objects. I then want to use the name of that object to select from amongst a group of HTML elements. Using the following does not work either (returns null):
document.getElementById(foo)
Thank you.
There is no reliable way to get the name of the object.
Example:
var obj = {};
var obj1 = obj;
var obj2 = obj;
magically_get_and_print_name(obj); // What to print? "obj"? "obj1"? "obj2"?
Methods to get the name in some cases:
Function declarations - funcreference.name (non-standard, though well-supported)
Constructor instances - instance.constructor.name
Let's say you have:
var someObj = {
a: 15,
b: 36
};
And then you did:
var foo = someObj;
There's no way to get the string "someObj" (or "foo") from foo.
What you could do, is add the name to the object when creating it. Something like this:
var someObj = {
a: 15,
b: 36,
objName: 'someObj'
};
var foo = someObj;
console.log(foo.objName); // "someObj"
Is it possible to create get/set function for undefined properties,
like in PHP __get() and __set() ?
You can access JavaScript object properties values using array access notation, you can also create a new property at any time using this notation or regular assignment notation.
var myObject = {};
myObject.Name = "Luis";
alert(myObject.Name);
alert(myObject["Name"]);
myObject["Name"] = "Dany";
alert(myObject.Name);
You can do
function ClassName(arg) {
var v = arg;
this.getter = function {
return v;
};
this.setter = function(val) {
v = val;
};
}
when you use it
var cn = new ClassName('a');
cn.setter('b');
alert(cn.getter()); /* alerts value 'b' */
Note that this uses the Constructor Invocation Pattern. By convention, you need to declare the function/class name with capital letter to indicate that this function/class need to be declared with the 'new' keyword.
Hope this helps
I saw this code before, but I don't know what the meaning:
var person1 = {
toLocaleString : function(){
return "Nikolaos";
},
toString : function(){
return "Nicholas";
}
}
var person2 = {
toLocaleString : function(){
return "bum";
},
toString : function(){
return "Greg";
}
}
var people = [person1, person2];
alert(people.toString());
alert(people.toLocaleString());
does the function create an object with the method of toLocaleString and toString??or...??
That code is doing three things:
Using object literal syntax to create object instances
Using anonymous function expressions to create functions and bind them to properties on the objects. (Functions are first-class objects in JavaScript, so you can keep references to them, pass the references around, etc.)
Specifically, it's overriding two standard functions that all JavaScript objects inherit from the Object prototype.
Let's break it down a bit.
1) Object literal notation:
var obj = {propName: propValue};
The { and } in this case denote an object literal. Within an object literal, you can write propName: propValue to assign propValue to the property with the name propName on the object. This is the same as:
var obj = {}; // Get an empty object
obj.propName = propValue; // Add a property to it
You can do multiple properties separated with commas. So for instance:
var obj = {
author: "Douglas Adams",
title: "The Hitchhiker's Guide to the Galaxy",
answer: 42
};
That creates an object with three properties, two with string values and one with a number value.
Note that the right-hand side are processed just like an assignment, and so can be anything that can appear on the right-hand side of an assignment statement:
var x = "bar";
var obj = {
three: 1 + 2,
fubar: "foo " + x
};
The property names can be put in quotes if you like:
var x = "bar";
var obj = {
"three": 1 + 2,
"fubar": "foo " + x
};
...which is handy for specifying properties that have the names of reserved tokens (like "if", or "return") or formerly-reserved tokens (like "class") where it would be a syntax error if they weren't in quotes.
2) Now let's look at function expressions:
var f = function() { /* your code here */ };
That's a function expression. It creates a new function and assigns a reference to it to the variable f. You can call it by calling f().
var f = function(name) {
alert("Hi " + name);
};
f("Fred"); // alerts "Hi Fred"
1 + 2) So putting it together with object literal notation:
var obj = {
foo: function(name) {
alert("Hi " + name);
}
};
obj.foo("Fred"); // alerts "Hi Fred"
(I don't like anonymous functions, I prefer my functions to have names, but that's another topic.)
3) And finally: As maerics pointed out, the specific functions that are being used in that code are toString and toLocaleString, both of which are standard functions of JavaScript objects. That means that those will override the standard version and so return the given values whenever the standard function would have been called.
The toString() and toLocaleString() methods are implemented for all JavaScript objects by the specification of the language. So arrays (such as the one stored in the "people" variable) seem to implement those methods by returning each of their elements' string or "locale string" value, respectively (at least, in the web browsers we are testing).
That is, the Array class toString and toLocaleString methods must be implemented with something like:
Array.prototype.toString = function() {
var a = [];
for (var i=0; i<this.length; i++) {
a[i] = this[i].toString(); // Note "toString".
}
return a.join(",");
}
Array.prototype.toLocaleString = function() {
var a = [];
for (var i=0; i<this.length; i++) {
a[i] = this[i].toLocaleString(); // Note "toLocaleString".
}
return a.join(",");
}