1. The name attribute

The name attribute of a function that returns the name of the function.

Function foo() {} foo.name // "foo" has long been widely supported by browsers, but it wasn't until ES6 that it was written into the standard.Copy the code

Note that ES6 makes some changes to the behavior of this property. If you assign an anonymous function to a variable, ES5’s name property returns an empty string, and ES6’s name property returns an empty string

Returns the actual function name.

var func1 = function () {};
// ES5
func1.name // ""
// ES6
func1.name // "func1"
Copy the code

In the above code, the variable func1 is equal to an anonymous function, and ES5 and ES6 return different values for the name attribute.

If a named function is assigned to a variable, the name attribute in both ES5 and ES6 returns the original name of the named function.

const bar = function baz() {}; // ES5 bar.name // "baz" // ES6 bar.name // "baz" // ES6 bar.name // "baz" // ES6 bar.name // "baz" // ES6 bar.name // "baz" (new Function).name // "anonymous" bind returns the Function whose name attribute value is prefixed with "bound". function foo() {}; foo.bind({}).name // "bound foo" (function(){}).bind({}).name // "bound "Copy the code

2. Arrow function

1.ES6 allows functions to be defined using arrows (=>).

var f = v => v; Var f = function(v) {return v; }; If the arrow function requires no arguments or multiple arguments, a parenthesis is used to represent the argument part. var f = () => 5; Var f = function () {return 5}; var sum = (num1, num2) => num1 + num2; Var sum = function(num1, num2) {return num1 + num2; };Copy the code

If the arrow function has more than one statement in its code block, enclose them in braces and return them with a return statement.

var sum = (num1, num2) => { return num1 + num2; }
Copy the code

Since braces are interpreted as blocks of code, if an arrow function returns an object directly, parentheses must be placed around the object.

var getTempItem = id => ({ id: id, name: "Temp" });
Copy the code

Arrow functions can be used in conjunction with variable deconstruction.

const full = ({ first, last }) => first + ' ' + last; Function full(person) {return person.first + "+ person.last; }Copy the code

2. The arrow function makes the expression more concise.

const isEven = n => n % 2 == 0;
const square = n => n * n;
Copy the code

The above code takes only two lines to define two simple utility functions. If I didn’t use the arrow function, I’d probably take up more lines, and I wouldn’t be as bold as I am now.

3. One use of the arrow function is to simplify the callback function.

[1,2,3].map(function (x) {return x * x; }); [1,2,3]. Map (x => x * x); Var result = values. Sort (function (a, b) {return a - b; }); Var result = values. Sort ((a, b) => a - b); Here is an example of rest parameters combined with arrow functions. const numbers = (... nums) => nums; // [1,2,3,4,5] const headAndTail = (head,... tail) => [head, tail]; HeadAndTail (1, 2,3,4,5) // [1,[2,3,4,5]]Copy the code

4. There are several caveats when using the arrow function.

(1) The this object in the function body is the object where it is defined, not where it is used.

(2) Can not be used as a constructor, that is, you can not use the new command, otherwise an error will be thrown. (3) Do not use arguments. This object does not exist in the function body. If so, use the Rest parameter instead.

(4) The yield command cannot be used, so the arrow function cannot be used as a Generator function.

Of the four above, the first is particularly noteworthy. The point of the this object is mutable, but in the arrow function, it is fixed.

function foo() {
setTimeout(() => {
console.log('id:', this.id);
}, 100);
}

var id = 21;
foo.call({ id: 42 });
// id: 42
Copy the code

In the above code, the argument to setTimeout is an arrow function whose definition takes effect when foo is generated, but whose actual execution takes place 100 milliseconds later. If it were a normal function, this would point to the global object window, and it would print 21. However, the arrow function causes this to always point to the object where the function definition was in effect (in this case, {id: 42}), so 42 is printed. The arrow function can make this, in setTimeout, bind to the scope where it was defined, instead of pointing to the scope where it was run. Here’s another example.

function Timer() { this.s1 = 0; this.s2 = 0; SetInterval (() => this.s1++, 1000); SetInterval (function () {this.s2++; }, 1000); } var timer = new Timer(); setTimeout(() => console.log('s1: ', timer.s1), 3100); setTimeout(() => console.log('s2: ', timer.s2), 3100); // s1: 3 // s2: 0Copy the code

In the above code, the Timer function internally sets two timers, respectively using the arrow function and the normal function. The this binding of the former refers to the scope in which it is defined (that is, the Timer function), and the this of the latter refers to the scope in which it is run (that is, the global object). So, after 3100 milliseconds, timer.s1 has been updated three times, but timer.s2 has not been updated once.

The arrow function makes this point immobilized, which is good for wrapping callbacks. Here is an example of a DOM event callback wrapped in an object.

var handler = { id: '123456', init: function() { document.addEventListener('click', event => this.doSomething(event.type), false); }, doSomething: function(type) { console.log('Handling ' + type + ' for ' + this.id); }};Copy the code

In the init method in the above code, we use the arrow function, which causes this in the arrow function to always point to the handler object. Otherwise, the callback function runs when this. DoSomething this

One line will get an error because this is pointing to the document object.

This is fixed not because the arrow function has an internal mechanism to bind this, but because the arrow function does not have its own this, so the internal this is the outer code block

Of this. Because it does not have this, it cannot be used as a constructor. So, the code for turning the arrow function into ES5 is as follows.

// ES6

function foo() {
setTimeout(() => {
console.log('id:', this.id);
}, 100);
}

// ES5

function foo() {
var _this = this;

setTimeout(function () {

console.log('id:', _this.id);

}, 100);

}
Copy the code

In the above code, the converted ES5 version makes it clear that the arrow function does not have its own this at all, but instead refers to the outer this.

How many “this” are there in the following code?

function foo() {
return () => {
return () => {
return () => {
console.log('id:', this.id);
};
};
};
}
var f = foo.call({id: 1});
var t1 = f.call({id: 2})()(); // id: 1
var t2 = f().call({id: 3})(); // id: 1
var t3 = f()().call({id: 4}); // id: 1
Copy the code

In the above code, there is only one “this”, which is the “this” of function foo, so t1, T2, and t3 all print the same result. Because all the inner functions are arrow functions, they don’t have their own this,

The “this” is actually the “this” of the outermost foo function.

In addition to this, the following variables do not exist in the arrow function, pointing to the corresponding variables of the outer function: arguments, super, and new.target.

function foo() {
setTimeout(() => {
console.log('args:', arguments);
}, 100);
}

foo(2, 4, 6, 8)
// args: [2, 4, 6, 8]
Copy the code

In the above code, the variable arguments inside the arrow function is actually the arguments variable for the function foo.

In addition, since the arrow function does not have its own this, of course, you cannot use call(), apply(), or bind() to change the point of this.

(function() {
return [
(() => this.x).bind({ x: 'inner' })()
];
}).call({ x: 'outer' });
// ['outer']
Copy the code

In the above code, the arrow function does not have its own this, so the bind method is invalid, and the internal this points to the external this. The JavaScript language’s This object has long been a headache, and you have to be very careful when using this in object methods. The arrow function “binds” to this, which solves this problem to a large extent.

Inside the arrow function, you can use the arrow function again. Here is a multinested function in ES5 syntax.

function insert(value) { return {into: function (array) { return {after: function (afterValue) { array.splice(array.indexOf(afterValue) + 1, 0, value); return array; }}; }}; } insert(2).into([1, 3]).after(1); //[1, 2, 3] the above function can be rewritten using the arrow function. let insert = (value) => ({into: (array) => ({after: (afterValue) => { array.splice(array.indexOf(afterValue) + 1, 0, value); return array; }})}); insert(2).into([1, 3]).after(1); //[1, 2, 3] The following is an example of deploying a pipeline mechanism, where the output of one function is the input of the next. const pipeline = (... funcs) => val => funcs.reduce((a, b) => b(a), val); const plus1 = a => a + 1; const mult2 = a => a * 2; const addThenMult = pipeline(plus1, mult2); AddThenMult (5) // 12 const plus1 = a => a + 1; const mult2 = a => a * 2; Mult2 (plus1(5)) // 12 The arrow function has another function, which is to conveniently rewrite the calculus of λ. / / lambda calculus writing fix = lambda f. (lambda x.f (lambda v.x (x) (v))) (lambda x.f (lambda v.x (x) (v))) / / written ES6 var fix = f = > (x = > f (v = > x (x) (v))) (x = > f (v = > x(x)(v)));Copy the code

There is almost a one-to-one correspondence between these two ways of writing