understanding lexical arguments in ES2015 - ecmascript-6

I was looking at:
https://babeljs.io/learn-es2015/
And it has the following example:
// Lexical arguments
function square() {
let example = () => {
let numbers = [];
for (let number of arguments) {
numbers.push(number * number);
}
return numbers;
};
return example();
}
square(2, 4, 7.5, 8, 11.5, 21); // returns: [4, 16, 56.25, 64, 132.25, 441]
and I was trying to understand what was really happening here:
specifically can someone explain why does square use an internal arrow function instead of just performing the required actions?
could this not be re-written to be:
function square() {
let numbers = [];
for (let number of arguments) {
numbers.push(number * number);
}
return numbers;
}
What does the extra wrapping in "example" change in the behavior of this function?

It simply demonstrates that arguments in the arrow function refers to arguments of square function. this is not true with a simple function :
function square() {
let example = function() {
let numbers = [];
for (let number of arguments) {
numbers.push(number * number);
}
return numbers;
};
return example();
}
square(2, 4, 7.5, 8, 11.5, 21); // returns: []

Related

Is there a way to signify an ignored/throwaway/wildcard value in ES2015?

What I'm looking for is a is something like the underscore on line 5:
const returnValues = () => {
const foo = {'one': 1}
const bar = {'two': 2}
return {
foo, bar
}
}
const { _, valueToBeUsed } = returnValues();
//do things with valueToBeUsed
It'd be nice and clean to have a way to signify that I don't need the first variable.
Some pattern-matching languages like Swift and Haskell call this a wildcard pattern.
Your returnValues function contains invalid syntax. If you meant to use array destructuring here, you can treat the array as an Object instead:
const returnValues = () => {
return [ 1, 2 ];
}
const { 1: valueToBeUsed } = returnValues();
console.log(valueToBeUsed); // 2
If returnValues should return an object, you do not need to destructure unused properties at all:
const returnValues = () => {
return { one: 1, two: 2 };
}
const { two: valueToBeUsed } = returnValues();
console.log(valueToBeUsed); // 2

Combinations of array values using google appscript

Here is my JS code
var allArrays = new Array(['a', 'b'], ['c', 'z'], ['d', 'e', 'f']);
function getPermutation(array, prefix) {
prefix = prefix || '';
if (!array.length) {
return prefix;
}
var result = array[0].reduce(function (result, value) {
return result.concat(getPermutation(array.slice(1), prefix + value));
}, []);
return result;
}
console.log(getPermutation(allArrays));
Now when I convert the same to Google Appscript it doesnt seem to work at all. What am i missing?
For a start console.log() doesn't work in GScript, replace it with Logger.log().
Putting it into a GScript it seems to work fine:
function test_getPermutation() {
var allArrays = new Array(['a', 'b'], ['c', 'z'], ['d', 'e', 'f']);
function getPermutation(array, prefix) {
prefix = prefix || '';
if (!array.length) {
return prefix;
}
var result = array[0].reduce(function (result, value) {
return result.concat(getPermutation(array.slice(1), prefix + value));
}, []);
return result;
}
Logger.log(getPermutation(allArrays)); // [16-10-12 10:27:36:400 BST] [acd, ace, acf, azd, aze, azf, bcd, bce, bcf, bzd, bze, bzf]
}

Why does the es6 version of my function say "Cannot read property 'forEach' of undefined"

This version of my es6 function doesn't work:
Array.prototype.concatAll = () => {
let results = [];
this.forEach((subArray) => {
subArray.forEach((item) => {
results.push(item);
});
});
return results;
};
When I use it like this:
var stocks = exchanges.concatAll();
The console says: Cannot read property 'forEach' of undefined
However this es5 version works just fine:
Array.prototype.concatAll = function() {
let results = [];
this.forEach((subArray) => {
subArray.forEach((item) => {
results.push(item);
});
});
return results;
};
Why is this? What exactly is happening with this inside the es6 version? I would like to understand.
This has already been mentioned, but this isn't a good use-case for arrow functions due to the fact that they bind the value of this. Another way you can do this with ES6 is to use Object.assign.
For your example:
Object.assign(Array.prototype, {
concatAll() {
let results = [];
this.forEach(subArr => {
subArr.forEach(item => {
results.push(item);
});
});
return results;
}
});
And then you could just use the code like this:
let arr = [
[1, 2, 3],
[4, 5, 6]
];
console.log(arr.concatAll()); // -> [1, 2, 3, 4, 5, 6]
You can also add on multiple methods like this:
Object.assign(Array.prototype, {
sum() {
return this.reduce((a, b) => a + b);
},
max() {
return this.reduce((a, b) => (a > b) ? a : b);
},
min() {
return this.reduce((a, b) => (a < b) ? a : b);
}
});
let arr = [1, 2, 3];
console.log(arr.sum()); // -> 6
console.log(arr.max()); // -> 3
console.log(arr.min()); // -> 1
The arrow function's scope of this is it's parent scope. So in this case this is undefined. So in this case you would still need a function.
Check the start of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions.
An arrow function expression (also known as fat arrow function) has a shorter syntax compared to function expressions and lexically binds the this value (does not bind its own this, arguments, super, or new.target). Arrow functions are always anonymous.
ES6 can still simplify your code though by using for of:
Array.prototype.concatAll = function(){
let results = []
for(let subArray of this)
for(let item of subArray)
results.push(item)
return results
}

TypeScript: difference between function types

What's the formal difference between the types of these two variables in TypeScript?
var randomStringId = () => Math.random().toString(36).substr(2, 9);
function randomStringId2() {
return Math.random().toString(36).substr(2, 9);
}
randomStringId has type () => string. randomStringId2 has type (): string. Are they different? If yes, how? Or is it just my IDE showing differently two types that are fundamentally the same?
Your functions are the same.
However, these two functions are not:
var getX = () => this.x
function getX() {
return this.x
}
look at the generated js code:
var _this = this;
var getX = function () {
return _this.x;
};
function getX() {
return this.x;
}
The function defined with arrow notation () => captures the reference to this when it is defined.
Absolutely no difference in the Types. Both are exactly the same. They take nothing and return a string.
Here is the proof :
interface Foo1{
foo:()=>string;
}
interface Foo2{
foo():string;
}
var foo1:Foo1;
var foo2:Foo2;
foo1 = foo2 = foo1;
However there is a difference in the way they behave. To understand the need for a lambda function ()=> : http://youtube.com/watch?v=tvocUcbCupA&hd=1

AS3 arguments

Why do you think the code below does not work?
What would you change/add to make it work?
Any help is appreciated..
function TraceIt(message:String, num:int)
{
trace(message, num);
}
function aa(f:Function, ...args):void
{
bb(f, args);
}
aa(TraceIt, "test", 1);
var func:Function = null;
var argum:Array = null;
function bb(f:Function, ...args):void
{
func = f;
argum = args;
exec();
}
function exec()
{
func.apply(null, argum);
}
I get an ArgumentError (Error #1063):
Argument count mismatch on test_fla::MainTimeline/TraceIt(). Expected 2, got 1.
..so, the passed parameter (argum) fails to provide all passed arguments..
..Please keep the function structure (traffic) intact.. I need a solution using the same functions in the same order.. I have to pass the args to a variable and use them in the exec() method above..
regards
Ok, here is the solution.. after breaking my head : )
function TraceIt(message:String, num:int)
{
trace(message, num);
}
function aa(f:Function=null, ...args):void
{
var newArgs:Array = args as Array;
newArgs.unshift(f);
bb.apply(null, newArgs);
}
aa(TraceIt, "test", 1);
var func:Function = null;
var argum:*;
function bb(f:Function=null, ...args):void
{
func = f;
argum = args as Array;
exec();
}
function exec():void
{
if (func == null) { return; }
func.apply(this, argum);
}
This way, you can pass arguments as variables to a different function and execute them..
Thanks to everyone taking the time to help...
When TraceIt() eventually gets called, it's being called with 1 Array parameter, not a String and int parameters.
You could change TraceIt() to:
function TraceIt(args:Array)
{
trace(args[0], args[1]);
}
Or you could change exec() to:
function exec()
{
func.apply(null, argum[0].toString().split(","));
}
...as it appears when you pass "test", 1, you end up with array whose first value is "test,1". This solution doesn't work beyond the trivial case, though.
Change your bb function to look like this:
function bb(f:Function, args:Array):void
{
func = f;
argum = args;
exec();
}
As you have it now, it accepts a variable number of arguments, but you are passing in an array(of the arguments) from aa.