Function extension of ECMAScript6

Keywords: REST Java Attribute ECMAScript

Function extension of ECMAScript6

1. Default value of function parameter

ES6 set the default value for function parameters before, which needs to be implemented with flexible methods.

function add(x, y) {
	x = x || 1;
	y = y || 2;
	return x+y; 
}

// Use parameter default value to participate in operation
add(); // 3
add(2); // 4

ES6 allows you to set default values for function parameters, which can be written directly after the parameter definition.

function add(x=1, y =2) {
	return x + y;
}

add(); // 3

When you set a default value for a function parameter, the function cannot have a parameter with the same name.

// When setting default values for function parameters, parameters with the same name cannot be included
function add (x = 1, x = 3, y = 1) {} // SyntaxError: Duplicate parameter name not allowed in this context
function add (x, x, y = 2) {} // SyntaxError: Duplicate parameter name not allowed in this context

The default value of a function parameter can be an expression or an object property. But the default value of the parameter is lazy evaluation, which will only be evaluated when it is used.

let person = {
	name: 'jidi',
	age: 22,
	sex: 1
}
let x = 12;

function printStr(y = x + 1, z = person) {
	console.log(y + z.age);
}

// Lazy evaluation of function parameter default value
printStr(); // 35
printStr(1); // 23

1.1 combination of function parameter default value and deconstruction assignment

Function parameters can be deconstructed and assigned. The default value of deconstruction and assignment can be used in combination with the default value of function parameters.

// Use deconstruction assignment defaults alone
function printStr ({x, y = 5}) {
	console.info(x, y);
}

// No parameters are provided. Parameters x and y will not be generated through deconstruction and assignment, thus error is reported
printStr(); // TypeError: Cannot destructure property 'x' of 'undefined' as it is undefined.

printStr({x:1}); // 1 5
printStr({}); // undefined 5
printStr({X:1, y:2}); // 1 2

In the above code, only the default value of the object's deconstruction assignment is used. Only when the parameter of the function printStr is an object, the variables x and y will be generated through the deconstruction assignment. If the function printStr is called without parameters, the variables x and y will not be generated and an error will be reported.

// Use deconstruction assignment defaults in combination with function parameter defaults
function printStr({x = 1 , y = 2 } = {}) {
	console.info(x, y);
}

// Do not add parameters, normal use
printStr(); // 1 2

In the above code, the default value is set for the function parameter. When the function is called, the default value will be called for deconstruction and assignment.

Here is a more obvious example.

// The default value of deconstruction assignment is set, and the default value of function parameter is {}
function m1 ({x = 0, y = 0} = {}) {
	return [x, y];
}
// There is no default value set for deconstruction assignment. The default value set for function parameter is an object
function m2 ({ x, y }  = { x:1, y: 2 }) {
	return [x, y];
}

// All parameters are empty
m1(); // [0, 0]
m2(); // [1, 2]

// x and y have values
m1({x: 2, y: 4}) // [2, 4]
m2({x: 2, y: 4}) // [2, 4]

// x has value, y has no value
m1({x: 8}) // [8, 0]
m2({x: 3}) // [3, undefined]

// No value for x and y
m1({}) // [0, 0];
m2({}) // [undefined, undefined]

In the above example, m1 sets the default value of object deconstruction and assignment, and the default value of function parameter is empty. No matter whether the parameter is set during function call, deconstruction and assignment will occur, and the value will be obtained according to the actual situation. If the deconstruction fails, the default value of Deconstruction and assignment will be used. m2 only sets the default value of function parameter, but not the default value of object deconstruction and assignment. When the function is called, the default value of deconstruction and assignment will be used When using, if the function has parameters, it will be deconstructed according to the actual situation. Because the default value is not set for deconstruction, the deconstruction is not successful, and the variable value will become undefined.

1.2 location of default value of function parameter

In general, the parameter that defines the default value is the tail parameter of the function. If the non trailing parameter is set to the default value, in fact, this parameter cannot be omitted unless the undefined placeholder is used.

function f(x = 1, y) {
  return [x, y];
}

f(); // [1, undefined]
f(2); // [2, undefined])

// Omit the parameter with default value and report error
f(, 1); // Uncaught SyntaxError: Unexpected token ','

// In order to be called correctly, the undefined placeholder must be displayed
f(undefined, 1) // [1, 1]

1.3 length attribute of function

When a function parameter specifies a default value, the length property of the function returns the number of parameters without a default value. This is because the meaning of the length property is the number of arguments that the function expects to pass in.

// When the default value is set, the expected number of parameters will be different from the actual number
(function (x) {}).length; // 1
(function (x = 5) {}).length; // 0
(function (x, y, z = 5) {}).length; // 2

1.4 scope

Once the default value of the parameter is set, the parameter will form a separate scope when the function is declared and initialized. After initialization, the scope disappears.

var x = 1;

function test(x, y = x) {
  console.log(y);
}

test(2); // 2

In the above code, when the function test is called, the parameters form a separate scope. In this scope, the default value variable x points to the first parameter x, and does not point to the global variable x, so the output result is 2.

var x = 1;

function test(y = x) {
  let x = 2;
  console.log(y);
}

test(); // 1

In the above code, when the function test is called, the parameters form a separate scope. In this scope, the default value variable x is not defined. At this time, it points to the global variable x, while the local variable x inside the function does not affect the default value variable x, so the output result is 1.

2. rest parameter

ES6 introduces the rest parameter (in the form of...), which is used to obtain redundant parameters of the function.

function add(...values) {
  let total= 0;

  for (let value of values) {
    total+= value;
  }
  return total;
}

add(1, 2, 3); // 6

rest parameter is a real array, and array specific methods can be used.

function printStr(...items) {
  items.forEach((item) => {
    console.log(item);
  });
}

printStr(1, 2, 3); // 1 2 3

The rest parameter can only be followed by the last parameter, otherwise an error will be reported.

function f(x, ...y, z) { } // Uncaught SyntaxError: Rest parameter must be last formal parameter

The length property of the function, excluding the rest parameter.

(function(...x) {}).length;  // 0

3. Strict mode

Starting with ES5, strict mode can be set inside the function. However, ES2016 has made some modifications to stipulate that as long as the function parameters use default values, deconstruction assignment, or extension operators, the internal function cannot be explicitly set to strict mode, otherwise an error will be reported.

// The function parameter uses the default value, and the internal use of strict mode will result in an error: illegal 'use strict' directive in function with non simple parameter list
function test(x, y = x) {
  'use strict';
}

// The function parameter uses the default value, and the internal strict mode will report an error
function test ({x, y}) {
  'use strict';
};

// Function parameters use extension operators. If strict mode is used internally, an error will be reported
function test (...a) => {
  'use strict';
};

4. Arrow function

ES6 allows you to define functions using "arrows" (= >).

var f = function(x) {
	return x;
} 

// The above example can be rewritten as follows with arrow function
var f = x => x;

If the function has no arguments or multiple arguments, you need to use parentheses.

// No parameters 
var f = () => "jidi";
// Equivalent to
var f = function() {
	return "jidi";
}

// There are multiple parameters
var f = (x, y) => x + y;
// Equivalent to
var f = function (x, y) {
	return x + y;
}

If there is more than one statement in the code block of the arrow function, enclose them with braces ({}), and return them with the return statement.

var sum = (x, y) => { return x + y; }

If the arrow function returns an object directly, parentheses must be added outside the object, otherwise an error will be reported.

// If the returned object is an object, parenthesis should be added outside the object, otherwise an error will be reported.
let getPerson = id => { id: id, name: "jidi" }; // Uncaught SyntaxError: Unexpected token ':'

// Parenthesized, no error reported
let getPerson = id => ({ id: id, name: "jidi" });

getPerson(1); // {id: 1, name: "jidi"}

Arrow functions can be used in conjunction with variable deconstruction.

// Arrow function with deconstruction assignment
const getStr= ({ name = "jidi", age = 22 } = {}) => name+ ' ' + age;

// Equate to
function getStr({ name = "jidi", age = 22 } = {}) {
  return name+ ' ' + age;
}

getStr(); // "jidi 22"
getStr({name: "java", age: 20}); // "java 20"

The arrow function can be used in conjunction with the rest parameter.

const numbers = (...number) => number;
// The rest parameter is an array, and the result returns an array
numbers(1, 2, 3, 4, 5); // [1,2,3,4,5]

// Use arrow function and rest parameter to calculate the sum of n numbers
const add = (...items) => {
	let total = 0;
	items.forEach(item => total += item)
	return total;
}

add(1, 2, 3); // 6

4.1 precautions for using arrow function

Although arrow function is more convenient to use, there are also some points needing attention of value.

  • this object in the function body is the object when the function is defined, not the object when it is used.
  • Cannot be used as a constructor, i.e. cannot use the new command.
  • The arguments object cannot be used because it does not exist inside the arrow function and can be replaced with the rest parameter.
  • If you cannot use the yield command, the arrow function cannot be used as a Generator function.

The direction of this object is variable, but in the arrow function, it is fixed.

var id = 21;

// Arrow function form
function f1() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}
f1(); // id: 21
f1.call({ id: 42 }); // id: 42

// Normal function form
function f2() {
  setTimeout(function() {
    console.log('id:', this.id);
  }, 100);
}
f2();  // id: 21
f2.call({ id: 42 }); // id: 21

In the above code, the parameter of setTimeout is an arrow function. When the definition of the arrow function takes effect, when the f1 function is generated, the arrow function causes this to always point to the object where the function definition takes effect, so the output is 42. For ordinary functions, this points to the global object during execution, and the output should be 21.

This point is fixed. In fact, the arrow function does not have its own this, so the internal this is the external code block's this. So if the code in the above example is converted to ES5 code, it is in the following form.

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

// ES5
function f1() {
  var _this = this;
  setTimeout(() => {
    console.log('id:', _this.id);
  }, 100);
}

In addition to this, arguments, super, and new.target do not exist in the arrow function. They also point to the corresponding variables of the outer function.

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

f(2, 4, 6, 8); // arguments: [2, 4, 6, 8]

In the above example, the srcomments variable inside the arrow function points to the arguments variable of the outer function f.

Because the arrow function does not have its own this, you cannot use call(), apply(), bind() to change the direction of this.

4.2 where arrow function is not applicable

Arrow function can fix this. There are two places where arrow function cannot be used.

  • Defines the method of the object, and the object method contains this.
  • When you need to use this dynamically, you cannot use the arrow function.

5. Trailing comma of function parameter

ES2017 allows the last argument of a function to have a trailing comma.

// ES2017 allows function parameters to be followed by commas
function add(x, y,) {
	return x + y;
}

6. Function.prototype.toString()

ES2019 changes toString() method of function instance. As like as two peas, the toString () method returns the function code omitted by annotations and spaces. The modified toStirng() method returns the same code.

function add(...items) {
    // Summation function
    let total = 0;
    items.forEach(item => total += item);
    return total;
} 

add.toString();	// "function add(...items) {
				//	   //Summation function
				//	   let total = 0;
				//	   items.forEach(item => total += item);
				//	   return total;
				//	}"

7. Parameter omission of catch command

try...catch structure. It was previously required that the catch command must be followed by a parameter to accept the error object thrown by the try code block. ES2019 has changed to allow the catch statement to omit parameters.

8. Reference link

This blog post is my own learning notes. Please refer to the following for the original text: Getting started with ECMAScript 6
If you have any questions, please point out in time!
Welcome to communicate, email: jidi_jidi@163.com.

Published 15 original articles, won praise 3, visited 3620
Private letter follow

Posted by ArneR on Thu, 27 Feb 2020 20:57:27 -0800