当前位置:网站首页>How to use parameters in ES6

How to use parameters in ES6

2020-11-06 01:22:48 :::::::

ECMAScript 6( Or call it ECMAScript 2015) yes ECMAScript The latest standard of , Greatly improved JavaScript The ability to process parameters in . Now we can use it rest Parameters (rest parameters)、 The default value is (default values) And deconstruction (destructuring) And many other new features . In this article we will explore the parameters (arguments) And parameters (parameter) In every way , to glance at ES6 How to improve and improve them .

Arguments and Parameters

arguments and Parameters The meaning of is usually interchangeable . For all that , For the purpose of this article , Or make a distinction . In most standards , When a function is declared, it is called parameters( Or call it formal parameters), And what's passed to the function is called arguments( Or call it actual arguments), Look at the following functions :

function foo(param1, param2) {
    // do something
}
foo(10, 20);

In this function ,param1 and param2 It's a function parameters, And the value passed to the function (10 and 20) yes arguments.

translator's note : There is no distinction later in this paper arguments and parameters, Unified translation parameters .

Extension operator (...)

stay ES5 in ,apply() Method can easily pass an array as an argument to a function , Often used to use Math.max() To get the maximum value of the array . Look at the following code snippet :

var myArray = [5, 10, 50];
Math.max(myArray);    // Error: NaN
Math.max.apply(Math, myArray);    // 50

Math.max() Method does not support arrays , Only numbers are accepted as parameters . When an array is passed to a function , Function will throw an error . But when used apply() After the method , The array becomes a separate array passed to the function , therefore Math.max() It can be executed correctly .

Fortunately, ,ES6 It brings us extension operators , We don't have to continue to use apply() The method . We can easily expand the expression into multiple parameters .

var myArray = [5, 10, 50];
Math.max(...myArray);    // 50

Here we use the extension operator to myArray Expanded into individual values . although ES5 We can pass apply() Method to simulate the extension operator , But it's grammatically confusing , And the lack of scalability . Extension operators are not only easy to use , It also brings a lot of new features . such as , You can use the extension operator more than once in a function call , And it can be mixed with other parameters .

function myFunction() {
  for(var i in arguments){
    console.log(arguments[i]);
  }
}
var params = [10, 15];
myFunction(5, ...params, 20, ...[25]);    // 5 10 15 20 25

Another great advantage of extension operators is that they can easily interact with constructors (constructor) Use it together :

new Date(...[2016, 5, 6]);    // Mon Jun 06 2016 00:00:00 GMT-0700 (Pacific Daylight Time)

At present, we can use ES5 To rewrite the code above , But we need a complex way to avoid a typo :

new Date.apply(null, [2016, 4, 24]);    // TypeError: Date.apply is not a constructor
new (Function.prototype.bind.apply(Date, [null].concat([2016, 5, 6])));   // Mon Jun 06 2016 00:00:00 GMT-0700 (Pacific Daylight Time)

REST Parameters

rest Parameters and extension operators are the same syntax , But he doesn't expand the array into parameters , Instead, it converts each parameter into an array .

translator's note :rest Parameters and extension operators have the same syntax , Here you can see the author's emphasis on arguments and parameters The difference between the . The extension operator is used for the parameters of the function call (arguments) in , and rest Parameters are used for the parameters of the function declaration (parameters) in .

function myFunction(...options) {
     return options;
}
myFunction('a', 'b', 'c');      // ["a", "b", "c"]

If no parameters are provided ,rest The parameter will be set to an empty array :

function myFunction(...options) {
     return options;
}
myFunction();      // []

When creating visible functions ( A function that accepts a variable number of arguments ) When ,rest Parameters are very useful . because rest The argument is an array , So it's easy to replace arguments object ( It will be discussed later ). Look at the next one using ES5 The method of writing :

function checkSubstrings(string) {
  for (var i = 1; i < arguments.length; i++) {
    if (string.indexOf(arguments[i]) === -1) {
      return false;
    }
  }
  return true;
}
checkSubstrings('this is a string', 'is', 'this');   // true

This function checks whether a string contains a specified series of strings . The first problem with this function is , We have to look at the body of the function to know that the function takes more than one parameter . in addition arguments Must be iterated from 1 Start , because arguments[0] Is the first parameter . If we add parameters after the first parameter later , Maybe we forgot to update this cycle . Use rest Parameters , We can easily avoid this problem :

function checkSubstrings(string, ...keys) {
  for (var key of keys) {
    if (string.indexOf(key) === -1) {
      return false;
    }
  }
  return true;
}
checkSubstrings('this is a string', 'is', 'this');   // true

The output of the function is the same as the previous function . Repeat... Again ,string Parameter is passed in as the first parameter , The remaining parameters are crammed into an array and assigned to variables keys.

Use rest Parameters instead of arguments It not only improves the readability of the code , And avoid JavaScript Medium Performance issues . For all that ,rest Parameters cannot be used without restrictions , for instance , It can only be the last parameter , Otherwise, it will lead to grammatical errors .

function logArguments(a, ...params, b) {
        console.log(a, params, b);
}
logArguments(5, 10, 15);    // SyntaxError: parameter after rest parameter

Only one is allowed when another restricts method declaration rest Parameters :

function logArguments(...param1, ...param2) {
}
logArguments(5, 10, 15);    // SyntaxError: parameter after rest parameter

The default value is

ES5 Default parameters in

ES5 in JavaScript Default values are not supported , But here's a very simple implementation , Use OR Operator (||), We can easily simulate the default parameters , Look at the code below :

function foo(param1, param2) {
   param1 = param1 || 10;
   param2 = param2 || 10;
   console.log(param1, param2);
}
foo(5, 5);  // 5 5
foo(5);    // 5 10
foo();    // 10 10

This function expects to receive two parameters , But when called without parameters , It will use the default value . Within the function , The missing parameter is automatically set to undefined, So we check these parameters , And give them default values . To detect missing parameters and set default values , We use OR Operator (||). This operator first checks the first value , If it is truthy, The operator will return it , Otherwise, the second parameter is returned .

This method is very common in functions , But there are also flaws . If you deliver 0 perhaps null It also returns the default value . Because they are thought to be falsy value . So if we really need to pass functions 0 perhaps null, We need another way to detect missing parameters :

function foo(param1, param2) {
  if(param1 === undefined){
    param1 = 10;
  }
  if(param2 === undefined){
    param2 = 10;
  }
  console.log(param1, param2);
}
foo(0, null);    // 0, null
foo();    // 10, 10

In this function , By checking whether the type of the parameter is undefined To determine if you want to assign a default value to . This method has a little bit more code , But it's safer , Let's pass the function 0 perhaps null.

ES6 Default parameters in

ES6 in , We don't have to check whether the parameter is undefined To simulate the default parameters , We can declare the default parameter function directly .

function foo(a = 10, b = 10) {
  console.log(a, b);
}
foo(5);    // 5 10
foo(0, null);    // 0 null

As you can see , Ignoring parameters returns the default value , But pass on 0 perhaps null did not . We can even use functions to generate default values for parameters :

function getParam() {
    alert("getParam was called");
    return 3;
}
function multiply(param1, param2 = getParam()) {
    return param1 * param2;
}
multiply(2, 5);     // 10
multiply(2);     // 6 (also displays an alert dialog)

It should be noted that , Only when the second parameter is missing ,gegParam Method will be executed , So when we use two parameters multiply() It doesn't pop up alert.

Another interesting feature of default parameters is that other parameters and variables can be referenced as default parameters in method declaration :

function myFunction(a=10, b=a) {
     console.log('a = ' + a + '; b = '  + b);
}
myFunction();     // a=10; b=10
myFunction(22);    // a=22; b=22
myFunction(2, 4);    // a=2; b=4

You can even execute the operator when the function is declared :

function myFunction(a, b = ++a, c = a*b) {
     console.log(c);
}
myFunction(5);    // 36

Be careful : Unlike other languages ,JavaScript The default parameters are calculated at call time :

function add(value, array = []) {
  array.push(value);
  return array;
}
add(5);    // [5]
add(6);    // [6], not [5, 6]

Deconstruct assignment

The deconstruction assignment is ES6 New features , Let's extract values from arrays or objects and assign them to variables , Syntax is similar to object and array literals . When you pass parameters to a function , This grammar is clear and easy to understand and practical .

stay ES5 in , Configuration objects are often used to handle a large number of optional parameters , Especially when the order of attributes doesn't matter , Look at the following functions :

function initiateTransfer(options) {
    var  protocol = options.protocol,
        port = options.port,
        delay = options.delay,
        retries = options.retries,
        timeout = options.timeout,
        log = options.log;
    // code to initiate transfer
}
options = {
  protocol: 'http',
  port: 800,
  delay: 150,
  retries: 10,
  timeout: 500,
  log: true
};
initiateTransfer(options);

This model JavaScript Developers often use , And it's easy to use . But we have to go into the function body to know how many parameters we need , Use the deconstruction parameter assignment , We can clearly specify the required parameters in the function declaration .

function initiateTransfer({protocol, port, delay, retries, timeout, log}) {
     // code to initiate transfer
};
var options = {
  protocol: 'http',
  port: 800,
  delay: 150,
  retries: 10,
  timeout: 500,
  log: true
}
initiateTransfer(options);

In this function , We use the object deconstruction pattern , Instead of a configuration object , Make our code clearer and easier to read .

We can also mix deconstruction parameters with ordinary parameters :

function initiateTransfer(param1, {protocol, port, delay, retries, timeout, log}) {
     // code to initiate transfer
}
initiateTransfer('some value', options);

We need to pay attention to , If the deconstruction parameter is missing during a function call, a type error will be thrown :

function initiateTransfer({protocol, port, delay, retries, timeout, log}) {
     // code to initiate transfer
}
initiateTransfer();  // TypeError: Cannot match against 'undefined' or 'null'

When our parameters are required , This kind of behavior is what we want , But what if we expect parameters to be optional ? To stop this mistake , We need to give the deconstruction parameter a default value :

function initiateTransfer({protocol, port, delay, retries, timeout, log} = {}) {
     // code to initiate transfer
}
initiateTransfer();    // no error

In this function , We assign an empty object to the deconstruction parameter as the default value . Now if the function is called without parameters , No errors will be thrown .

We can also assign default values to each attribute of the deconstruction parameter :

function initiateTransfer({
    protocol = 'http',
    port = 800,
    delay = 150,
    retries = 10,
    timeout = 500,
    log = true
}) {
     // code to initiate transfer
}

In this case , Each attribute is given a default value , There's no need to check manually in the function body undefined The default value is given to the parameter of .

Parameter passing

There are two ways to transfer function parameters : Reference passing and value passing . If it's reference passing , Modifying parameters will cause global changes , If it's value transfer , It will only cause changes within the function .

In some languages , image Visual Basic and PowerShell, We can choose whether the declaration is value passing or reference passing , but JavaScript Not so .

Value passed

Strictly speaking ,JavaScript Only value passing . When we pass a value to a function, we pass a parameter , This worthy copy is created in the scope of the function . So any change worth changing will only be reflected in the function itself . See the following example :

var a = 5;
function increment(a) {
    a = ++a;
    console.log(a);
}
increment(a);   // 6
console.log(a);    // 5

ad locum , Modifying parameters inside a function does not affect the original value . So print this variable out of the function , The result is always 5.

reference

stay JavaScript in , It's all value passing , But when we pass a variable to an object ( Including arrays ), This “ value ” It points to this object , Changing a certain aspect of an object can also cause changes in its associated objects .

Look at this function :

function foo(param){
    param.bar = 'new value';
}
obj = {
    bar : 'value'
}
console.log(obj.bar);   // value
foo(obj);
console.log(obj.bar);   // new value

As you can see , The properties of the object are modified within the body of the function , But it affects objects outside the function .

When we pass a non primitive value , Like arrays or objects , The program creates an object in memory , Point to the original address . If it's modified , The original value will also be modified .

Type checking and missing or redundant parameters

In strongly typed languages , We have to declare the type of the parameter when we declare the function , but JavaScript There is no such feature in , stay JavaScript in , It doesn't care about the type and number of arguments passed to the function .

Suppose we have a function , Only one parameter is accepted . When we call this function , We don't limit how many arguments are passed to the function , You can even choose not to pass , It doesn't make mistakes .

The number of parameters can be divided into two cases :

  • Missing parameter The missing variable is assigned to undefined
  • Too many parameters Redundant parameters are ignored , But from arguments Variable ( The following is a discussion of ).

Force parameters

If a function is missing in a function call , It will be set to undefined. We can use that , If the parameter is missing, an error is thrown :

function foo(mandatory, optional) {
    if (mandatory === undefined) {
        throw new Error('Missing parameter: mandatory');
    }
}

stay ES6 in , We can get closer , Use default parameters to set mandatory parameters :

function throwError() {
    throw new Error('Missing parameter');
}
function foo(param1 = throwError(), param2 = throwError()) {
    // do something
}
foo(10, 20);    // ok
foo(10);   // Error: missing parameter

arguments object

stay ES4 The default parameters are added when , Instead of arguments object , but ES4 It didn't happen . With ES6 Release ,JavaScript Now the official support for default parameters . But it didn't cancel support arguments The plan for .

arguments An object is an array of classes , You can take... Out of all the functions .arguments Get the parameters passed in through a numeric index , Not by the name of the parameter . This object allows us to pass any number of arguments to the function . Look at the code below to judge :

function checkParams(param1) {
    console.log(param1);    // 2
    console.log(arguments[0], arguments[1]);    // 2 3
    console.log(param1 + arguments[0]);    // 4
}
checkParams(2, 3);

This function expects to pass in an argument , When we call it with two arguments , We go through param1 perhaps arguments[0] To get the first parameter , But the second parameter can only be passed through arguments[1] obtain . That is said ,arguments Objects can be used with named parameters .

arguments Object contains all the parameters of the passed in function , And the index starts with 1. When we want to get more parameters , We will use arguments[2]arguments[3] wait .

We can skip all parameter naming settings , Only use arguments object :

function checkParams() {
    console.log(arguments[1], arguments[0], arguments[2]);
}
checkParams(2, 4, 6);  // 4 2 6

actually , Named parameters are a convenience , But not necessarily . alike ,rest Parameters can also be used to display incoming parameters :

function checkParams(...params) {
    console.log(params[1], params[0], params[2]);    // 4 2 6
    console.log(arguments[1], arguments[0], arguments[2]);    // 4 2 6
}
checkParams(2, 4, 6);

arguments Object is an array like object , But it lacks the image of slice and foreach Other methods . In order to be in arguments Use these methods on objects , It needs to be converted to a real array :

function sort() {
    var a = Array.prototype.slice.call(arguments);
    return a.sort();
}
sort(40, 20, 50, 30);    // [20, 30, 40, 50]

In this function , Use Array.prototype.slice.call() Fast will arguments Object to array . And then use sort Method to sort .

ES6 There is a more direct way ,Array.from(),ES6 New method , Used to create a new array from class array objects .

function sort() {
    var a = Array.from(arguments);
    return a.sort();
}
sort(40, 20, 50, 30);    // [20, 30, 40, 50]

length attribute

although arguments Objects are not strictly arrays , But it has one length attribute , Can be used to check the number of arguments passed to the function .

function countArguments() {
    console.log(arguments.length);
}
countArguments();    // 0
countArguments(10, null, "string");    // 3

By using length attribute , We can better control the number of parameters . for instance , If a function needs two parameters , We can use length Property to check the number of parameters , If it's less than expected, it throws an error .

function foo(param1, param2) {
    if (arguments.length < 2) {
        throw new Error("This function expects at least two arguments");
    } else if (arguments.length === 2) {
        // do something
    }
}

rest Parameters are arrays , So he also has length attribute , We use it ES6 To rewrite the method above :

function foo(...params) {
  if (params.length < 2) {
        throw new Error("This function expects at least two arguments");
    } else if (params.length === 2) {
        // do something
    }
}

Callee and Caller attribute

callee Property points to the currently running function , and caller Point to the function that calls the currently running function . stay ES5 In strict mode , These attributes are obsolete , If you want to access them, you throw an error .

arguments.callee Properties in recursive functions ( Recursive function is a common function , Point to itself by its signature ) It's very useful , Especially when the signature of the function is not available ( That's anonymous functions ). Because anonymous functions don't have names , The only way to point to yourself is through arguments.callee.

var result = (function(n) {
  if (n <= 1) {
    return 1;
  } else {
    return n * arguments.callee(n - 1);
  }
})(4);   // 24

Strict mode and non strict mode arguments

stay ES5 Non strict mode , arguments Objects have an unusual feature : It keeps synchronized with the named parameter values .

function foo(param) {
   console.log(param === arguments[0]);    // true
   arguments[0] = 500;
   console.log(param === arguments[0]);    // true
   return param
}
foo(200);    // 500

Inside the function , A new value is assigned to arguments[0]. because arguments Always in sync with the value of the named parameter ,arguments[0] The change of the will also cause param Changes . in fact , They are different names for the same variable . stay ES5 In strict mode , This confusing feature has been removed :

"use strict";
function foo(param) {
   console.log(param === arguments[0]);    // true
   arguments[0] = 500;
   console.log(param === arguments[0]);    // false
   return param
}
foo(200);   // 200

This time, ,arguments[0] The change of has not affected param, And the output is the same as expected .ES6 Next , Output sum ES5 The strict pattern is consistent . But remember , Default parameters are used in function declaration ,arguments Unaffected .

function foo(param1, param2 = 10, param3 = 20) {
   console.log(param1 === arguments[0]);    // true
   console.log(param2 === arguments[1]);    // true
   console.log(param3 === arguments[2]);    // false
   console.log(arguments[2]);    // undefined
   console.log(param3);    // 20
}
foo('string1', 'string2');

In this function , Even though param3 Have default values , But he and arguments[2] It's not equal , Because only two parameters are passed into the function . in other words , Setting default parameters does not affect arguments object .

Conclusion

ES6 to JavaScript It brought a lot of improvements, big and small . More and more developers are using ES6, And many of the features are accessible . In this article we have learned ES6 How to improve JavaScript The ability to process parameters . But we just learned ES6 A little bit of skin . There are more interesting features waiting to be discovered !


Look at the time. It's just 23:23, It took almost a whole afternoon and evening to read and translate this article , This article combines ES5 and ES6 To explain , It's a lot of money . But the level of translation is limited , Please give more advice and advice ~

Original address : How To Use Arguments And Parameters In ECMAScript 6

Little ad

Welcome to our WeChat official account :

Participation of this paper Tencent cloud media sharing plan , You are welcome to join us , share .

版权声明
本文为[:::::::]所创,转载请带上原文链接,感谢