I'm sure this thing is duplicated somewhere but I don't know what to search.
So, I've been looking through a Node.JS Application and found this code and wondered what it does. I have tried searching but I don't know what to search so I was hoping someone would it explain it to me.
init = refresh = function () {
// code here..
};
I understand 1 equals, but why 2? does it make some sort of alias so that function can be run with both init and refresh?
= resolves the right hand side and then assigns the result to the left hand side.
The result of doing this is the same as the result assigned.
So that assigns the function to both init and refresh
Quentin did a very good job telling you what it is doing.
I just wanted to chime in to give an example where you might use this:
Say for instance you have an object:
var obj = {
init: function() {
var x = this.x = [1,2,3];
}
};
What this allows you to do is reference your x variable two different ways (either through x or this.x).
Now why would you do this?
Well two major reasons.
It is faster to access x rather than this.x (but you still need to access it elsewhere)
It produces easier to read code when having to read/write to x lots of times in one function.
This is just another reason why you would use it.
But in most cases it is just aliases, such as: forEach -> each
Here's an explanation using operator associativity and precedence.
So, looking at an operator precedence description from Mozilla, when an expression includes multiple operators of the same precedence, as in
a OP b OP c
, then you check whether that level of precedence uses right-to-left or left-to-right associativity.
a = b = c
The assignment operator in JavaScript is the only operator on its level of precedence.
It has right-to-left associativity
So in a = b = c, b = c is evaluated first, assigning the value of c to b.
Then the expression becomes a = b.
Related
I have the following adding function, which appeared originally here.
add takes only one argument, but it may do so an 'infinite' number of times through the 'magic' of currying and closures.
function add (a) {
var f = b => add(a + b);
f.valueOf = () => a;
return f;
}
var add4 = add(2)(2);
var add6 = add4(2);
var add10 = add6(2)(2);
var add14 = add10(2)+2;
//var add16 = add14(2); no longer works because of type conversion above.
console.log(+add4, +add6, +add10, add14);
//logs 4, 6, 10, 14
You can see, above, that the function can keep creating functions with new a values that can go on taking additional arguments. The function can also act as a normal variable for the purpose of math operations, such as var sum = add(x)+y;.
However, once the type conversion takes place, the sum from the previous example ceases to be a function and is converted to a number.
Now that the background is out of the way, my questions is this: is there a (relatively easy) way to prevent the type coercion of the add function while still allowing it to be used in arithmetic operations? Or, in other words, is there a simple way to directly modify the valueOf (and/or a values) without adding much boilerplate (preferrably while maintaining the add(x)+y; structure)?
I think that the coercion to number you are trying to avoid does not relate to add() function, it is the way '+' operator of Javascript works. Therefore changing this behavior is not an 'easy' task. It could take changing the way javascript parser work.
The simplest workaround I can think of (not sure of course how exactly you are using this function) is to always wrap the result with extra add() call, e.g.:
add(2)(3) + 8; // 13, number
can be wrapped like this:
add( add(2)(3) + 8 ); // function with valueOf = 13
Again, not sure about your exact use case though.
So basic desctucturing is fine, {a, b} = obj transpiles to a = obj.a; b = obj.b.
My question is around a bit of an odd syntax that I accidentally ran across and I'm wondering if someone can point me at spec since I can't find it:
({a, b} = obj).c
That does the two a, b assignments and then returns obj.c. It's actually quite useful to me for a byte stream decoder, as I can write:
let width = ({bytes} = intDecode(bytes)).number;
My issue is that I haven't seen this syntax anywhere and don't want to rely on something that is either incorrectly implemented or in proposal stage.
There is nothing special in Destructuring Assignment: it's evaluated as any other Assignment with = operator.
So it returns rval.
Which means you can rely on your syntax.
Some details:
The Destructuring Part is evaluated in the 6[1]:
Let status be the result of performing DestructuringAssignmentEvaluation of assignmentPattern using rval as the argument.
and after this item the assignment evaluation happens as usually, like in the a = b = 42; case.
References:
12.14.4 Assignment Operators / Runtime Semantics: Evaluation
12.14.5.2 Destructuring Assignment / Runtime Semantics: DestructuringAssignmentEvaluation
Yes, it is expected to work like this (see #zerkms' answer for details). That you haven't seen the syntax anywhere is because it's not exactly good practice to access properties on the result of an assignment expression, as it makes the code quite unreadable. Whether you assign to a normal variable or a destructuring expression doesn't make much difference here.
However, you could quite easily transform the code into a reasonable destructuring assignment:
let {bytes, number:width} = intDecode(bytes);
or actually, more closely to your original code:
let width;
({bytes, number:width} = intDecode(bytes));
very basic JavaScript programmer here!
I was busy on some code with variables that look like this:
blocktype1;
blocktype2;
blocktype3;
blocktype4;
... //everything between blocktype4 and blocktype70, the three dots are not actual code!
blocktype70;
Now I was using eval() in a function where a value was given to one of the blocktype variables. The blocktype depended on the variable "number".
This is what I had for that part:
eval("blocktype" + number) = 3
What I want is, say "number" is 27, then I want the variable blocktype27 to get a value of 3.
When I check the console it says:
ReferenceError: Invalid left-hand side in assignment
Could anyone possibly help me?
I would prefer just vanilla JavaScript and still the use of eval.
Thank you for your time!
The 'correct' solution would probably be to use an Array which is ideal for sequences and are accessible by index.
var number = 1;
var val = 3;
var blocktype = []; // so clean
blocktype[number] = val;
However, properties can be accessed as with the bracket notation as well. This assumes the variables are in global scope and are thus properties of the global (window) object.
var blocktype1; // .. etc
window["blocktype" + number] = val;
The problem with the eval is that is effectively the same as doing f() = 3 which does not make sense: only variables/properties can be assigned to1.
However eval is a built-in function and the results of a function cannot be assigned to, per the error message. It could be written as
var blocktype1; // .. etc (see dandavis' comment)
eval("blocktype" + number + " = " + val);
// What is actually eval'd is:
// eval("blocktype1 = 3")
which quickly exposes a flaw with eval. If val was the string "Hello world!" with would result in eval("blocktype1 = Hello world!") which is clearly invalid.
1 For the gritty: the left-hand side of an assignment has to be a Reference Specification Type, which is a more wordy way of describining the above behavior. (It is not possible for a JavaScript function to return a RST, although it could technically be done for vendor host objects.)
Feel free not to accept this, since it's specifically not using eval(), but:
You can allocate an array of size 71 like so:
var blocktype = new Array(71);
(your number values apparently start at 1, so we'll have to ignore the first element, blocktype[0], and leave room for blocktype[70], the 71st)
You can now assign elements like this:
blocktype[number] = 3;
and use them like so:
alert( blocktype[number] );
I have written the following code
o[s += "a"] = o[s += "b"] = o[s += "c"] = 0;
I was curious as to why the variable s ends up storing "abc" and not "cba". It seems like it would be easier for the the code to execute from right to left.
I seems as though the executor chooses and index for storage then decides what goes in there, but doing this make it sound slower since there would be so many states and memory being pushed onto the stack. Can somebody explain as to why it makes sense for the code to execute in the order that is does?
I have included a fiddle with a few more examples. http://jsfiddle.net/eggrdtuk/3/
Luke's comment is right. We can look at the MDN page for operator precedence.
Computed Member Access has precedence 1 and Assignment has precedence 16. So the property access expressions are evaluated first, then the assignment operations. Furthermore, Computed Member Access has left-to-right associativity, while Assignment has right-to-left associativity.
So, we can think of the first step as parsing the property access expressions from left-to-right:
o["a"] = o["ab"] = o["abc"] = 0
and the second step as doing assigments from right-to-left:
(o["a"] = (o["ab"] = (o["abc"] = 0)))
(o["a"] = (o["ab"] = 0))
(o["a"] = 0)
I don't see how changing associativity for either step would change the performance. But if there is a reason, I would love to learn :)
Once, I saw an example like this:
var a, x, y;
var r = 10;
with (Math) {
a = PI * r * r;
x = r * cos(PI);
y = r * sin(PI / 2);
}
And it looks very convenience, because that way I don't have to type all the Math.s.
But when I take a look at the MDN, it says:
Using with is not recommended, and is forbidden in ECMAScript 5 strict mode. The recommended alternative is to assign the object whose properties you want to access to a temporary variable.
So is it okay to use with()? In HTML5?
The MDN you linked says Using with is not recommended...
with is an excellent way of making spaghetti code for lunch.
You might like it, but the guy that will need to debug it will curse you.
javascript has some very weird operators, like the comma operator(,).
Can you understand what the following code does?
var a = "a";
var b = "b";
a = [b][b = a,0];
Well it swaps a and b... You don't understand , so as the guy that will need maintain your with code. Don't use hacks, hacks are cool in charades games, not in real code.
When is the comma operator useful?
The comma swap Fiddle
It is okay to use any feature of JavaScript, so long as you understand it.
For example, using with you can access existing properties of an object, but you cannot create new ones.
Observe:
var obj = {a:1,b:2};
with(obj) {
a = 3;
c = 5;
}
// obj is now {a:3,b:2}, and there is a global variable c with the value 5
It can be useful for shortening code, such as:
with(elem.parentNode.children[elem.parentNode.children.length-3].lastChild.style) {
backgroundColor = "red";
color = "white";
fontWeight = "bold";
}
Because the properties of the style object already exist.
I hope this explanation is clear enough.
In his excellent book "Javascript: The Good Parts", Douglas Crockford lists the "with Statement" in Appendix B: The Bad Parts.
He says "Unfortunately its results can sometimes be unpredictable, so it should be avoided".
He goes on to give an example, where an assignment inside the with will operate on different variables depending on whether the object is defined or not.
See With statement considered harmful (but less detailed than the explanation in the book).