[ES6] function extension

1. Default values for function parameters

Basic Usage

Before ES6, you can't directly specify default values for function parameters. You can only use flexible methods.

function log(x, y){
    y = y || 'world'
    console.log(x,y)
}
log('hello')   //hello world
log('hello', 'china')   //hello china
log('hello', '')    //hello world

ES6 allows you to set default values for function parameters, that is, write them directly after the parameter definition

function log(x, y = 'world'){
    console.log(x, y)
}
log('hello')   //hello world
log('hello', 'china')   //hello china
log('hello', '')    //hello

Note: parameter variables are declared by default. In the function body, let or const cannot be used to declare again, otherwise an error will be reported. When using default parameters, the function cannot have parameters with the same name.

Used in conjunction with deconstruction assignment defaults

The default value of the parameter can be used in combination with the default value of the deconstruction assignment

function foo({x, y = 5}){
    console.log(x, y)
}
foo({})				//undefined  5
foo({x: 1 })   		//1   5
foo({x: 1, y: 2})   //1   2
foo()    //report errors

function foo2({x, y = 5} = {}){
	console.log(x, y)
}
foo()    //undefined   5

The location of the default value of the parameter

Generally, the parameter with the default value defined should be the tail parameter of the function. Because it is easier to see which parameters are omitted. If the non tail parameter is set to the default value, in fact, this parameter cannot be omitted.

function fn(x = 1, y){
	return [x, y]
}
fn()   //[1, undefined]
fn(2)  //[2, undefined]
fn(, 1)  //report errors
fn(undefined, 1)   //[1,1]

The length attribute of the function

After the default value is specified, the length property of the function will return the number of parameters without the specified default value. If the default value is encountered, the return length will be stopped directly, that is, the number of parameters before the default value appears for the first time

(function(a) {}).length   //1
(function(a = 5) {}).length  //0
(function(a,b,c = 5) {}).length   //2

Scope

Once the default value of the parameter is set, the parameter will form a separate context when the function is declared and initialized. After initialization, the scope will disappear. This syntax behavior will not appear when the parameter default value is not set.

var x = 1
function fn(x, y = x){
	console.log(y)
}
fn(2) //2

Explanation: the default value of parameter y is equal to variable x. When the function fn is called, the parameters form a separate scope. The default value of X is in the scope of the global variable, instead of the default value of X

Let's look at the following example:

let x = 1
function fn(y = x){
    let x = 2
    console.log(y)
}
fn()  //1

Explanation: when calling a function, the parameter y = x forms a separate scope. In this scope, the variable x itself is not defined, so it points to the outer global variable x. When calling a function, the local variable x inside the function body cannot affect the default value variable x. if the global variable X does not exist at this time, an error will be reported.

2. rest parameter

ES6 introduces the rest parameter (in the form of... Variable name) to obtain the redundant parameters of the function, so there is no need to use the arguments object. The variable matched with rest parameter is an array, which puts redundant parameters into the array (actually the inverse operation of extension operator)

function add(...val){
    let sum = 0
    for(var v of val){
        sum += v
    }
    return sum
}
add(2,5,3)   //10

The arguments object is not an array, but an array like object, so in order to use the array method, you must use array prototype. slice. Call first converts it into an array. The rest parameter does not have this problem. It is a real array.

3. Strict mode

Starting from ES5, the internal function can be set to strict mode

function todo(a,b){
    'use strict'
    //...
}

ES6 has made some modifications to stipulate that as long as the function parameters use default values, deconstruction assignment, or extension operators, the internal display of the function cannot be set to strict mode, otherwise an error will be reported

//report errors
function todo (a, b, c = 1){
    use 'strict'
    //...
}

4. name attribute

The name attribute of the function returns the function name of the function

function foo() {}
foo.name   // 'foo'

Note that ES6 has made some modifications to the behavior of this attribute. If an anonymous function is assigned to a variable, the name attribute of ES5 will return an empty string, while the name attribute of ES6 will return the actual function name

var fn = function () {}

//es5 
fn.name   //  ''

//es6
fn.name   //  'fn'

If a named function is assigned to a variable, the name properties of ES5 and ES6 will return the original name of the named function

const bar = function baz() {}
//es5
bar.name   // 'baz'
//es6
bar.name   //  'baz'

The Function instance returned by the Function constructor. The value of the name attribute is anonymous

(new Function).name    //'anonymous'

For the function returned by bind, the value of the name attribute will be prefixed with bound

function foo () {}
foo.bind({}).name   //  'bound foo'

(function(){}).bind({}).name   // 'bound'

5. Arrow function

Basic Usage

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

var fn = val => val

//Equivalent to
var fn = function(val){
    return val
}

If the arrow function does not require parameters or requires more than one parameter, a parenthesis is used to represent the parameter part

var fn = () => 5
//Equivalent to
var fn = function() {
    return 5
}

var sum = (num1, num2) => num1 + num2
//Equivalent to
var sum = function(num1,num2){
    return num1 + num2
}

If the code block of the arrow function is more than one statement, you need to enclose them in curly braces

var fn = (a,b) {
    if(a>b){
        return a
    }else{
        return b
    }
}

Since braces are interpreted as code blocks, if the arrow function directly returns an object, you must add parentheses outside the object, otherwise an error will be reported

//report errors
let getTem = id => {
    id: id,
    name: 'Temp'
}
//No error reporting
let getTem = id => ({
    id: id,
    name: 'Temp'
})

Precautions for use

The arrow function consists of several points for attention:
(1) this object in the function body is the object where the arrow function is defined, not the object where it is used
(2) It cannot be used as a constructor, that is, it cannot use the new command, otherwise an error will be reported
(3) The arguments object cannot be used. The arguments object inside the arrow function does not save arguments. You can use the rest parameter instead
(4) You cannot use the yield command, so the arrow function cannot be used as a Generator function

6. Tail call optimization

What is a tail call?

Tail Call is an important concept of functional programming, which means that the last step of a function is to call another function

function fn(x){
    return gn(x)
}

In the above code, the last step of function fn is to call function gn, which is called tail call

Tail call optimization

Note that only when the internal variables of the outer function are no longer used, the call frame of the inner function will replace the call frame of the outer function, otherwise the tail call optimization will not be possible

function addone(a){
    var one = 1
    function inner(b){
        return b + one
    }
    return inner(a)
}

Tags: ECMAScript

Posted by namasteaz on Thu, 14 Apr 2022 08:39:32 +0930