I know there are a ton of EloqJS questions on here, but I haven't seen this one asked and it is throwing me for a loop. I'm curious how the key squirrel in the object entry (squirrel: squirrel) is not replaced by the argument passed by the function in this code:
function addEntry(squirrel) {
var entry = {events: [], squirrel: squirrel};
for (var i = 1; i < arguments.length; i++)
entry.events.push(arguments[i]);
journal.push(entry);
}
addEntry(true, "work", "touched tree", "pizza",
"running", "television");
I would expect for it to entry to be {events: [], true: true}, but that is not what this is returning. What am I obviously missing here? Original code at http://eloquentjavascript.net/04_data.html#arguments_object
Because object keys are literals: they don't change at runtime or act as variables to be replaced with a value.
If you look at the object initialiser section of the spec (11.1.5), it specifies that an object literal consists of a property name/value list, with property name defined to be one of:
IdentifierName
StringLiteral
NumericLiteral
The rules for IdentifierName are defined in section 7.6 to include most unicode characters, but not reserved words or whitespace.
Any IdentifierName can be wrapped in quotes to become a valid StringLiteral, although the inverse is not always true (StringLiterals containing punctuation or whitespace need the quotes to be valid). You can define the object just as well with:
{'events': [], 'squirrel': squirrel}
As of ES6, there is now a notation to specify that a key should be the value of a variable rather than an identifier or literal of its own. This is defined in section 12.2.6 as a ComputedPropertyName, using the [expr] syntax. For the object to have a true: true property, you could use the ES6 code:
{'events': [], [squirrel]: squirrel}
That's because Object Literal Notation can't receive variables as object keys.
For example:
var name = "John";
var person = {
name: name
}
// person = { name: "John" }
var name = "John";
var person = {};
person[name] = name;
// person = { "John": "John" }
Related
With ES6, I can create a new object with functions like the following:
var obj = {
something() {}
};
That makes sense. But I can also do this:
var obj = {
'something'() {}
};
Or I can do this:
var obj = {
['something']() {}
};
Is there a difference between these three syntaxes? Why are all of these syntactically valid?
Is there a difference between these three syntaxes?
Not wrt to the results in your example.
However, the different syntaxes do have different characteristics. The way the property name is defined is not specific to method definitions btw, the rules apply to all property names:
Property names that are valid identifier names or number literals don't need to be quoted:
{
foo: ...,
10e4: ...,
if: ...,
}
Anything else needs to be quoted:
{
'foo+bar': ...,
'abc def': ...,
'123,45': ...,
}
The square bracket syntax is new in ES6 and allows you do dynamically compute property names:
{
[getPropertyName()]: ...,
['item' + (i * 3)]: ...,
}
Why are all of these syntactically valid?
Because the grammar allows it:
MethodDefinition :
PropertyName ( StrictFormalParameters ) { FunctionBody }
GeneratorMethod
get PropertyName ( ) { FunctionBody }
set PropertyName( PropertySetParameterList ) { FunctionBody }
PropertyName :
LiteralPropertyName
ComputedPropertyName
LiteralPropertyName :
IdentifierName
StringLiteral
NumericLiteral
ComputedPropertyName :
[ AssignmentExpression ]
(not sure what kind of answer you expect here)
If you consider methods to be equivalent to assigning a function to the property, it seems to make sense to apply the same rules for property names to function/method names.
First and second are the same, and do the same as
obj.something = function something() {}
the third one creates an anonymous function and stores it in obj.something. It's an equivalent to this:
obj['something'] = function() {}
Quotes allow to create keys (and hence function names) that are not valid identifiers in JS, for example:
var obj = {
'123'() {}
};
creates a function with the name 123, believe it or not.
The square brackets syntax allows arbitrary expressions, so you can do
var obj = {
['myfunc_' + getFuncName()] () {}
}
and similar cool things.
When specifying a key in an object's key-value pair (using the notation below) the interpreter (apparently) allows the use of strings:
var x = { 'color': '#fff' };
However specifying a key dinamically using a function (that returns a string) is not allowed:
function s()
{
return 'color';
}
var x = { s(): '#fff' };
I guess strings, when using that notation, must be static values.
However I cannot find JavaScript language specifications regarding that...
In this case you should use this method:
var x = {};
x[s()] = "#fff";
x[foo()] = "#000";
According to this MDN article (I highlight with bold):
The syntax for an object using an object initializer is:
var obj = { property_1: value_1, // property_# may be an identifier...
2: value_2, // or a number...
// ...,
"property n": value_n }; // or a string
where obj is the name of the new object, each property_i is an identifier (either a name, a number, or a string literal), and each value_i is an expression whose value is assigned to the property_i.
So in this literal notation it is not allowed to evaluate expressions, e.g. via function calls to determine the property identifiers.
In the ECMAScript Language Specification it is more formally put:
PropertyName:
IdentifierName
StringLiteral
NumericLiteral
ECMAScript 2015
With ECMAScript 2015 more becomes possible as explained in this MDN article:
Starting with ECMAScript 2015, the object initializer syntax also supports computed property names. That allows you to put an expression in brackets [ ], that will be computed as the property name.
// Computed property names (ES6)
var i = 0;
var a = {
["foo" + ++i]: i,
["foo" + ++i]: i,
["foo" + ++i]: i
};
The formal definition in the ECMAScript 2015 Language Specification has:
PropertyName:
LiteralPropertyName
ComputedPropertyName
ComputedPropertyName:
[ AssignmentExpression ]
So with ES6 you would rewrite your example like this:
function s()
{
return 'color';
}
var x = { [s()]: '#fff' };
"Associative arrays" do not exist in Javascript. You're probably referring to Objects. This is a pretty common mistake when learning JS.
An Object can be initialized using { }, or with the new operator like so :
var x = {};
var y = {foo : 'bar'};
var z = new Object();
When accessing an object properties, you can either use the . operator, or brackets.
var somevalue = y.foo; // 'bar'
var someother = y['foo'] // 'bar'
In your current situation, you'd want something like that :
var x = new Object(); // or {}
x[s()] = "#fff";
Object type
If you check the type of x, it will return 'object'.
var typeOfX = typeof x; // 'object'
I have the following that i entered into the mongo terminal and it works great
db.cars.update({'_id':'FordXdfg'},{$inc :{'attribs.0.totl':1}})
which basically updates an array using dot notation, the 0 is the index of the array.
this does work. but transferring it to node my 0 comes from a variable.
so i tried
var carIndex = 3;
cars.update({'_id':'FordXdfg'},{$inc :{'attribs.' + carIndex + '.totl':1}}, function (err, callback) ................)
seems to be invalid javascript, if i replace my carIndex with 3 then it works i.e.
cars.update({'_id':'FordXdfg'},{$inc :{'attribs.3.totl':1}}, function (err, callback) ................)
Any ideas?
thanks
When using that style of object initialization in JavaScript, property names must be string literals. When using the object initialization syntax, property names can not be constructed at run time in code. For example, you can only use literals like:
{
"name": "Martin"
"location": "Earth"
"value": 1234
}
You cannot do this:
var propName = "name";
var obj = {
propName: "Martin";
};
While it syntactically appears to work, you'll end up with an object that looks like:
{
propName: "Martin"
}
Again, that's because only literal values are accepted when constructing an object using the shortened syntax. It will not interpret variable values.
There are two other options for setting properties of a JavaScript object, either through simple dot-notation:
obj.name = "Martin";
Or, you can use bracket notation:
obj["name"] = "Martin";
As objects in JavaScript act like associative arrays in that you can define new properties/keys at runtime each with a value, either syntax above works, and both result in the same underlying storage (and can be used interchangeably).
So, you'll need to construct the $inc syntax separately using the other technique for setting object property values in JavaScript:
var inc = {};
inc["attribs." + carIndx + ".totl"] = 1;
Then use that inside of your update:
{ $inc: inc }
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.
What do the curly braces surrounding JavaScript arguments for functions do?
var port = chrome.extension.connect({name: "testing"});
port.postMessage({found: (count != undefined)});
A second possible answer has arisen since this question was asked. Javascript ES6 introduced Destructuring Assignment.
var x = function({ foo }) {
console.log(foo)
}
var y = {
bar: "hello",
foo: "Good bye"
}
x(y)
Result: "Good bye"
The curly braces denote an object literal. It is a way of sending key/value pairs of data.
So this:
var obj = {name: "testing"};
Is used like this to access the data.
obj.name; // gives you "testing"
You can give the object several comma separated key/value pairs, as long as the keys are unique.
var obj = {name: "testing",
another: "some other value",
"a-key": "needed quotes because of the hyphen"
};
You can also use square brackets to access the properties of the object.
This would be required in the case of the "a-key".
obj["a-key"] // gives you "needed quotes because of the hyphen"
Using the square brackets, you can access a value using a property name stored in a variable.
var some_variable = "name";
obj[ some_variable ] // gives you "testing"
Curly braces in javascript are used as shorthand to create objects. For example:
// Create an object with a key "name" initialized to the value "testing"
var test = { name : "testing" };
alert(test.name); // alerts "testing"
Check out Douglas Crockford's JavaScript Survey for more detail.
var x = {title: 'the title'};
defines an object literal that has properties on it. you can do
x.title
which will evaluate to 'the title;
this is a common technique for passing configurations to methods, which is what is going on here.