I'm trying to pass an argument to a function in Javascript. However, the argument column is being interpreted as a literal string as opposed to an argument to the function. This is due to the colon directly following the argument column:
update(column, selected) {
var cols = {...this.props.columns, column: selected}
this.props.dispatch(updateColumns({type: "UPDATE_COLUMNS", cols}))
}
I've tried using arguments[0] instead of column but then I am told arguments is a reserved word in strict mode. Any idea how I can get read this value as an argument as opposed to a string?
In modern JavaScript environments, object initializer syntax allows for expressions to be evaluated on the left side of the property initialization:
update(column, selected) {
var cols = {...this.props.columns, [column]: selected}
this.props.dispatch(updateColumns({type: "UPDATE_COLUMNS", cols}))
}
The square brackets mean that the expression inside should be evaluated, and the result should be used as the property name.
In older environments, you'd have to do it in a separate statement, but since you're already using spread syntax I'd guess you're not concerned with that.
Related
The internet, including Stackoverflow states that Javascript does not accept type specific parameters (one such article here). However, why does ES6 accept an array literal as the parameter for a function and when I pass a primitive it throws a Type Error?
I am having a hard time wrapping my head around what Javascript is doing in the background. I thought Javascript typically takes a variable name as the parameter in a function declaration and allocates memory for that name and assigns the value of whatever argument I pass to the parameter. I am not sure if this is exclusively in the Arguments Object or elsewhere also. In the example below, however, I do not have a variable name for the array literal. I just don't know how Javascript is interpreting this parameter.
In the code below I define a function using an array literal as the parameter and when I try to pass a primitive as an argument it produces a TypeError.
function box([width,height]) {
return `I have a box that is ${width} x ${height}`;
}
console.log(box([6,6])); //NO error
console.log(box(6)); //produces error, Webstorm says, "TypeError:
undefined is not a function"
This behavior is documented in the ES6 specification Destructuring assignments.
In the Runtime Semantics section, the definition of the array destructuring assignment is
ArrayAssignmentPattern : [ ]
Let iterator be GetIterator(value).
ReturnIfAbrupt(iterator).
Return IteratorClose(iterator, NormalCompletion(empty)).
It's pretty interesting to dig into it. The array destructuring assignment (so it is an assignment) expects an iterable, that is: an object for which obj[Symbol.iterator] is defined as a function returning an iterator. Try testing this in a console of a browser that supports it (tests done on Firefox 57). In fact when you do:
let [a,b] = 5 //smaller reproduction of the error
you will get TypeError: 5 is not iterable. Contrast with below:
let number = new Number(5);
number[Symbol.iterator] = function*() {
yield 5;
}
let [f,g] = number; // works, f === 5, g === undefined
Probably under the hood JS destructuring maps the named array indexes to a slot which represents the next iteration of the iterator. Numbers do not have a built-in [Symbol.iterator] property, hence the error
If I have an object and function
var obj {
"1234": {"example": "sample"},
"5678": {"example": "sample"}
}
function example(num, str) {
if obj[num].hasOwnProperty(str) {
//manipulate property
}
return obj;
}
then later call the function,
obj(1234, "example")
Why do I have to write obj[num] instead of obj.num? Shouldn't dot notation be acceptable because the value being passed will always be an integer and not have quotations around it, i.e. obj.1234 would work but not obj."string"?
Why do I have to write obj[num] instead of obj.num?
Because obj[num] takes the value of num (for instance, 1234) and uses that value as the property name, but obj.num uses "num" (literally) as the property name. Brackets vs. dot is how the JavaScript parser knows when you're giving the property name literally (dot notation) or using an expression you want to use the result of (brackets notation).
(Side note: Granted, when we do foo[1], we literally mean the property 1 in foo. But from the parser's perspective, we're effectively using an expression there.)
I have a basic function taking an argument. I will use this argument to as index to access the array in JSON file. I want to take advantage of this argument instead of hard-coded inside the function. However, for some reasons, javascript is not return me the right value.
var obj = {
"first":[
["aaaaa"],
["bbbbb"],
["ccccc"],
["ddddd"],
["eeeee"]
]
}
I have a javascript function to access the file.
function addElement(ID) {
console.log(obj.ID);
}
and now if I use
addElement("first"); //this return me undefined.
I do not want to explicitly mention obj.first in order to access the right JSON object. I would like to make it more generic so that the method can be re-used. Am I missing anything here?
Thanks...
JavaScript supports both dot notation and a property name literal (obj.foo), and brackets notation and a property name string (obj["foo"]).* In the latter case, the string can be the result of any expression.
So you'd need brackets notation, not dot notation:
function addElement(ID) {
console.log(obj[ID]);
}
obj.ID accesses the property ID. obj[ID] accesses the property whose name is the string from the variable ID.
* Just for completeness: In ES6, it will support property name Symbols in brackets notation as well, but that's not relevant to your code.
I'm confused by the = vs. : when assigning a value to a property in an object
Now I know that there are a couple ways to create an object:
Object Literal
Object Constructor
With an object Literal you would use ":" to assign a value to a property:
var myObject = {firstName: "John", lastName="Smith" };
There we are using ":" to set the value to the property.
I also know a function itself is an object. And you can probably expose public properties from there as part of the function being an object?
So is it if you're assigning a function to a property that you'd use "="? I am assuming yet but what about something like this:
var phantom = require('phantom');
var World = function World(callback) {
phantom.create("--web-security=no", "--ignore-ssl-errors=yes", { port: 12345 }, function (ph) {
var phantomProcess = ph;
createBrowserPage = function(){
phantomProcess.createPage(function(page) {
this.headlessPage = page;
})
};
});
callback();
};
module.exports.World = World;
I assume I have this right in that I want to expose createBrowserPage through exports. I wouldn't use createBrowserPage: and use a ":" instead of "=" to assign that anonymous function to the createBrowserPage property right?
= is used for assignment in a Javascript statement as in:
variable = "foo";
: is used in an object literal declaration between a property name: value as in:
var obj = {
prop1: value1,
prop2: value2
};
If you want to expose your createBrowserPage() function through exports, you have several options, some of which involve creating an object and some of which involve assigning a property to an object. Which you choose and how you declare it leads to whether you use : or =. It depends upon which way you choose to write the javascript code that exposes createBrowserPage(). There is no single answer there. I will offer you a couple options.
If, in one statement, you want to assign one new property to the exports object, then you would use = like this:
module.exports.myFunc1 = myLocalFunction1;
If, in one statement, you wish to assign all your exported functions, then you would assign an object that was assigned with =, but used : in the declaration of the object like this:
module.exports = {
myFunc1: myLocalFunction1,
myfunc2: myLocalFunction2
};
In the first example, you are adding one new property to the exports object and assigning that property a value.
In the second example, you are declaring a new Javascript literal object (which uses prop: value syntax to declare its properties. And, then you are assigning that whole object to module.exports which actually replaces the entire existing exports object with a new one and this new object has two properties on it.
Your question is a bit confusing, but if you're interested in the precise meaning and grammar of : and = it's like this:
The colon (:) symbol is not an operator, it is part of the litteral object notation syntax and separates property names (a litteral string or simple identifier) from their value (any expression). Colons are only used in that context and as part of the trinary conditional operator (?:).
Something in curly brackets is parsed as a litteral object if and only if the { is not the first character in the instruction (otherwise it defines a block) and does not follow a function expression or declaration.
The assignment operator (=) (spec) is a binary operator, it can be used in any expression as long as its left operand is a valid left-hand-side expression, and it returns the value of the right operand. Unless strict mode is used, it will silently fail to assign a value to read-only properties.
When using a returned value to determine the number of an element in an array, does javascript throw quotes around it?
Example :
This tallys the number of times unique characters are used.
var uniques = {};
function charFreq(s)
{
for(var i = 0; i < s.length; i++)
{
if(isNaN(uniques[s.charAt(i)])) uniques[s.charAt(i)] = 1;
else uniques[s.charAt(i)] = uniques[s.charAt(i)] + 1;
}
return uniques;
}
console.log(charFreq("ahasdsadhaeytyeyeyehahahdahsdhadhahhhhhhhhhha"));
It just seems funny that uniques[s.charAt(i)] works, and uniques[a] wont work (due to lack of quotes). uniques[a] will get you a nasty 'a is undefined'.
When you access a JavaScript object using the [] notation, you are using a string as a key in the object. You can also address properties using the . notation:
uniques.a is the same as uniques['a']
The reason you aren't adding quotes to the s.charAt(i) is that it returns a string, which is then used as the property to check on the uniques object.
uniques[a] will create an error, because no variable with the name a has been defined.
In the first version -- uniques[s.charAt(i)] -- you're doing the lookup using an expression. JavaScript evaluates the expression -- s.charAt(i) -- and uses the evaluated value (maybe a) to perform the lookup in the uniques map.
In the second version -- uniques[a] -- you want to do the lookup using the literal character a, but unless you wrap it in quotes then JavaScript treats the a as an expression rather than a literal. When it tries to evaluate the "expression" then you get an error.
So the rule is: character/string literals need quotes; expressions that evaluate to characters/strings don't.
This is how Javascript evaluates the expression between [] like uniques[s.charAt(i)] which is of the type MemberExpression[ Expression ] :
Let propertyNameReference be the result of evaluating Expression.
Let propertyNameValue be GetValue(propertyNameReference).
Let propertyNameString be ToString(propertyNameValue).
So in the 3rd step it is converting the property name into a string.