日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何使用ES6中的参数

發(fā)布時間:2025/3/8 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何使用ES6中的参数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

ECMAScript 6(或者叫 ECMAScript 2015)是 ECMAScript 的最新標(biāo)準(zhǔn),極大的提高了 JavaScript 中處理參數(shù)的能力。現(xiàn)在我們可以使用 rest 參數(shù)(rest parameters)、默認(rèn)值(default values)和解構(gòu)(destructuring)以及其他許多新的特性。本文我們將探索參數(shù)(arguments)和參數(shù)(parameter)的方方面面,看一下ES6是如何對他們改進(jìn)和提升的。

Arguments 和 Parameters

arguments 和 Parameters 的含義通常是可以互換的。盡管如此,為了本文的目標(biāo),還是要做出區(qū)分。在大多數(shù)的標(biāo)準(zhǔn)中,函數(shù)聲明時給出的叫做 parameters(或者叫 formal parameters),而傳遞給函數(shù)的叫做的 arguments(或者叫 actual arguments),看下面的函數(shù):

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

在這個函數(shù)中,param1 和 param2 是函數(shù)的 parameters,而傳遞給函數(shù)的值(10 和 20)是 arguments。

譯者注:本文后面不再區(qū)分 arguments 和 parameters,統(tǒng)一譯作參數(shù)。

擴(kuò)展運算符(...)

在 ES5 中,apply() 方法可以很方便將數(shù)組作為參數(shù)傳遞給函數(shù),經(jīng)常用于使用 Math.max() 來取得數(shù)組的最大值。看下面的代碼段:

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

Math.max() 方法不支持?jǐn)?shù)組,只接受數(shù)字作為參數(shù)。當(dāng)數(shù)組傳遞給函數(shù),函數(shù)會拋出錯誤。但是當(dāng)使用 apply() 方法后,數(shù)組變成了一個個單獨的數(shù)組傳遞給了函數(shù),所以 Math.max() 就能夠正確的執(zhí)行了。

幸運的是,ES6 給我們帶來了擴(kuò)展運算符,我們就不必再繼續(xù)使用 apply() 方法了。我們可以將表達(dá)式輕松的展開為多個參數(shù)。

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

在這里我們通過擴(kuò)展運算符將 myArray 展開成了一個個單獨的值。雖然 ES5 中我們可以通過 apply() 方法來模擬擴(kuò)展運算符,但是語法上讓人迷惑,并且缺少可擴(kuò)展性。擴(kuò)展運算符不僅易于使用,還帶來了許多新的特性。比如,你可以在函數(shù)調(diào)用時多次使用擴(kuò)展運算符,并且還可以和其他參數(shù)混合在一起。

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

擴(kuò)展運算符另一大好處就是他可以很容易的和構(gòu)造函數(shù)(constructor)一起使用:

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

當(dāng)前我們可以使用 ES5 來重寫上面的代碼,不過我們需要一個復(fù)雜的方法來避免一個類型錯誤:

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 參數(shù)

rest 參數(shù)和擴(kuò)展運算符是一樣的語法,但是他不是將數(shù)組展開成一個個的參數(shù),而是將一個個參數(shù)轉(zhuǎn)換為數(shù)組。

譯者注:rest 參數(shù)和擴(kuò)展運算符雖然一樣的語法,在這里你就可以看出作者強(qiáng)調(diào)的 arguments 和 parameters 的區(qū)別了。擴(kuò)展運算符用于函數(shù)調(diào)用的參數(shù)(arguments)中,而 rest 參數(shù)用于函數(shù)聲明的參數(shù)(parameters)中。

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

如果沒有提供參數(shù),rest 參數(shù)會被設(shè)置為空數(shù)組:

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

當(dāng)創(chuàng)建可見函數(shù)(接受數(shù)量可變的參數(shù)的函數(shù))的時候,rest 參數(shù)就顯得十分有用。因為 rest 參數(shù)是一個數(shù)組,所以可以很方便的替換 arguments 對象(將會在下文討論)。看下面一個使用 ES5 編寫的方法:

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

這個函數(shù)的作用是檢查一個字符串是否包含指定的一系列字符串。這個函數(shù)的第一個問題就是,我們必須查看函數(shù)體才知道函數(shù)接受多個參數(shù)。另外 arguments 的迭代必須從 1 開始,因為 arguments[0] 是第一個參數(shù)。如果我們稍后給第一參數(shù)之后再添加參數(shù),或許我們就忘記更新這個循環(huán)了。使用 rest 參數(shù),我們可以很輕易的避開這個問題:

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

函數(shù)的輸出和上一個函數(shù)一樣。再重復(fù)一次,string 參數(shù)作為第一個參數(shù)傳入,剩下的參數(shù)被塞進(jìn)一個數(shù)組并且賦值給了變量 keys。

使用 rest 參數(shù)代替 arguments 不僅提高了代碼的可讀性,并且避免了 JavaScript 中的性能問題。盡管如此,rest 參數(shù)并不能無限制使用,舉個例子,它只能是最后一個參數(shù),否則會導(dǎo)致語法錯誤。

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

另一個限制方法聲明時只允許一個 rest 參數(shù):

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

默認(rèn)值

ES5 中的默認(rèn)參數(shù)

ES5 中 JavaScript 并不支持默認(rèn)值,但這里有個很簡單的實現(xiàn),使用 OR
運算符(||),我們可以很容易的模擬默認(rèn)參數(shù),看下面的代碼:

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

這個函數(shù)期望接收兩個參數(shù),但當(dāng)無參數(shù)調(diào)用時,它會使用默認(rèn)值。在函數(shù)內(nèi),缺失的參數(shù)自動設(shè)置為 undefined,所以我們檢查這些參數(shù),并給他們設(shè)置默認(rèn)值。為了檢測缺失的參數(shù)并設(shè)置默認(rèn)值,我們使用 OR 運算符(||)。這個運算符首先檢查第一個值,如果是 truthy,運算符會返回它,否則返回第二個參數(shù)。

這種方法在函數(shù)內(nèi)很常用,但也存在瑕疵。如果傳遞 0 或者 null 也會返回默認(rèn)值。因為它們被認(rèn)為是 falsy 值。所以如果我們確實需要給函數(shù)傳遞 0 或者 null,我們需要換種方法來檢測參數(shù)是否缺失:

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

在這個函數(shù)中,通過檢查參數(shù)的類型是否為 undefined 來確定是否要賦予默認(rèn)值。這種方法代碼量稍微大一些,但更安全,可以讓我們給函數(shù)傳遞 0 或者 null。

ES6 中的默認(rèn)參數(shù)

ES6 中,我們不必再檢查參數(shù)是否為 undefined 來模擬默認(rèn)參數(shù),我們可以直接將默認(rèn)參數(shù)函數(shù)聲明中。

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

正如你所看到的,忽略參數(shù)返回了默認(rèn)值,但傳遞 0 或者 null 并沒有。我們甚至可以使用函數(shù)來產(chǎn)生參數(shù)的默認(rèn)值:

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)

需要注意的是,只有缺少第二個參數(shù)的時候,gegParam 方法才會執(zhí)行,所以當(dāng)我們使用兩個參數(shù) multiply() 的時候并不會彈出 alert。

默認(rèn)參數(shù)另一個有意思的特性是在方法聲明是可以引用其他參數(shù)和變量作為默認(rèn)參數(shù):

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

甚至可以在函數(shù)聲明的時候執(zhí)行操作符:

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

注意:不像其他語言,JavaScript 是在調(diào)用時才計算默認(rèn)參數(shù)的:

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

解構(gòu)賦值

解構(gòu)賦值是 ES6 的新特性,讓我們可以從數(shù)組或者對象中提取值并賦值給變量,語法上類似于對象和數(shù)組字面量。當(dāng)給函數(shù)傳參時,這種語法清晰且易于理解并且很實用。

在 ES5 中,經(jīng)常使用配置對象來處理大量的的可選參數(shù),尤其是屬性的順序無關(guān)緊要的時候,看下面的函數(shù):

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);

這種模式 JavaScript 開發(fā)者經(jīng)常使用,并且很好用。但我們必須進(jìn)入函數(shù)體內(nèi)才知道到底需要多少參數(shù),使用解構(gòu)參數(shù)賦值,我們可以在函數(shù)聲明時很清晰的指定需要的參數(shù)。

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);

在這個函數(shù)中,我們使用了對象解構(gòu)模式,而不是一個配置型對象,讓我們的代碼更加清晰易讀。

我們也可以混用解構(gòu)參數(shù)和普通參數(shù):

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

需要注意,如果函數(shù)調(diào)用時解構(gòu)參數(shù)缺失會拋出一個類型錯誤:

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

當(dāng)我們的參數(shù)是必須的,這種行為我們是想要的,但是如果我們期望參數(shù)可選呢?為阻止這種錯誤,我們需要給解構(gòu)參數(shù)賦一個默認(rèn)值:

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

在這個函數(shù)中,我們給解構(gòu)參數(shù)賦了一個空對象作為默認(rèn)值。現(xiàn)在如果函數(shù)調(diào)用時沒有賦予參數(shù),不會拋出錯誤。

我們也可以給解構(gòu)參數(shù)每個屬性都賦默認(rèn)值:

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

在這個例子中,每個屬性都被賦予默認(rèn)值,就無需在函數(shù)體內(nèi)手動檢查 undefined 的參數(shù)再賦予默認(rèn)值。

參數(shù)傳遞

函數(shù)傳參有兩種方式:引用傳遞和值傳遞。如果是引用傳遞,修改參數(shù)會引起全局的變化,如果是值傳遞,只會引起函數(shù)內(nèi)的變化。

在一些語言中,像 Visual Basic 和 PowerShell,我們可以選擇聲明是值傳遞還是引用傳遞,但 JavaScript 不是這樣。

值傳遞

嚴(yán)格來說,JavaScript只能值傳遞。當(dāng)我們通過值傳遞給函數(shù)傳參,就在函數(shù)作用域內(nèi)創(chuàng)建了這個值得副本。所以任何值得變化都只會反映在函數(shù)內(nèi)部。看下面的例子:

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

在這里,在函數(shù)內(nèi)部修改修改參數(shù)并不會影響到原始值。所以在函數(shù)外打印這個變量,得到的結(jié)果始終是 5。

引用傳遞

在 JavaScript 中,所有的都是值傳遞,但是當(dāng)我們傳遞一個變量指向一個對象(包括數(shù)組),這個“值”就指向了這個對象,改變了對象的某個屬相也會引起其關(guān)聯(lián)對象的改變。

看這個函數(shù):

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

正如你看到的,對象的屬性在函數(shù)體內(nèi)部被修改,但是卻影響到了函數(shù)外部的對象。

當(dāng)我們傳遞一個非原始的值,像數(shù)組或者對象,程序會在內(nèi)存中創(chuàng)建一個對象,指向原始地址。如果被修改,原始值也會隨之修改。

類型檢查和缺失或多余參數(shù)

在強(qiáng)類型的語言中,我們必須在函數(shù)聲明時聲明參數(shù)的類型,但 JavaScript 中沒有這種特性,在 JavaScript 中,并不關(guān)心傳遞給函數(shù)的參數(shù)的類型和個數(shù)。

假設(shè)我們有一個函數(shù),僅接受一個參數(shù)。當(dāng)我們調(diào)用這個函數(shù)的使用,我們并不限制到底傳遞給函數(shù)多少個參數(shù),甚至可以選擇不傳,都不會產(chǎn)生錯誤。

參數(shù)的個數(shù)可以分為兩種情況:

  • 參數(shù)缺失

    缺失的變量賦值為 undefined

  • 參數(shù)過多

    多余的參數(shù)會被忽略,但可以從 arguments 變量中取到(下文即將討論)。

強(qiáng)制參數(shù)

函數(shù)調(diào)用中如果函數(shù)缺失,它會被設(shè)置為 undefined。我們可以利用這一點,如果參數(shù)缺失就拋出錯誤:

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

在 ES6 中,我們可以更近一步,使用默認(rèn)參數(shù)來設(shè)置強(qiáng)制參數(shù):

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 對象

在 ES4 的時候默認(rèn)參數(shù)就被加入,來代替 arguments 對象,但 ES4 并沒有實現(xiàn)。隨著 ES6 的發(fā)布,JavaScript 現(xiàn)在官方支持了默認(rèn)參數(shù)。但并沒有取消支持 arguments 的計劃。

arguments 對象是一個類數(shù)組的對象,可以在所有的函數(shù)中取到。arguments 通過數(shù)字索引來獲取傳入的參數(shù),而不是通過參數(shù)的名字。這個對象允許我們給函數(shù)傳入任意多的參數(shù)。看下面的代碼判斷:

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

這個函數(shù)期望傳入一個參數(shù),當(dāng)我們傳入兩個參數(shù)調(diào)用它的時候,我們通過 param1 或者 arguments[0] 來獲取第一個參數(shù),但第二個參數(shù)只能通過 arguments[1] 獲取。也即是說,arguments 對象可以和有命名的參數(shù)一起使用。

arguments 對象包含了所有傳入函數(shù)的參數(shù),并且索引的起始是 1。當(dāng)我們希望獲取更多的參數(shù)的時候,我們會使用 arguments[2] 、arguments[3] 等等。

我們可以跳過所有的參數(shù)命名設(shè)置,僅僅使用 arguments 對象:

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

實際上,命名的參數(shù)是一種方便,但不是必需的。同樣的,rest 參數(shù)也可以用來顯示傳入的參數(shù):

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

arguments 對象是一個類數(shù)組對象,但是缺少像 slice 和 foreach 等方法。為了在 arguments 對象上使用這些方法,需要將其轉(zhuǎn)換為真實的數(shù)組:

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

在這個函數(shù)中,使用 Array.prototype.slice.call() 快速將 arguments 對象轉(zhuǎn)換為數(shù)組。然后使用 sort 方法進(jìn)行排序。

ES6 有一種更直接的方法,Array.from(),ES6 新增的方法,用來通過類數(shù)組對象創(chuàng)建一個新的數(shù)組。

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

length 屬性

雖然 arguments 對象并不是嚴(yán)格意義的數(shù)組,但它有一個 length 屬性,可以用來檢查傳遞給函數(shù)的參數(shù)的個數(shù)。

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

通過使用 length 屬性,我們可以更好的控制參數(shù)的數(shù)量。比如說,如果一個函數(shù)需要兩個參數(shù),我們就可以使用 length 屬性來檢查參數(shù)數(shù)量,如果少于期望數(shù)量就拋出錯誤。

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 參數(shù)是數(shù)組,所以他也有 length 屬性,我們用 ES6 來重寫上面的方法:

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 和 Caller 屬性

callee 屬性指向當(dāng)前正在運行的函數(shù),而 caller 指向調(diào)用當(dāng)前正在運行函數(shù)的函數(shù)。在 ES5 嚴(yán)格模式下,這些屬性是被廢棄掉的,如果要訪問它們會拋出錯誤。

arguments.callee 屬性在遞歸函數(shù)(遞歸函數(shù)是一個普通函數(shù),通過它的簽名指向自身)下很有用,尤其是函數(shù)的簽名不可用時(也就是匿名函數(shù))。因為匿名函數(shù)沒有名字,唯一指向自身的方法就是通過 arguments.callee。

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

嚴(yán)格模式和非嚴(yán)格模式下的 arguments

在 ES5 非嚴(yán)格模式下, arguments 對象有一個不常用的特性:它保持和命名參數(shù)值同步。

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

在函數(shù)內(nèi)部,一個新的值賦給 arguments[0]。因為 arguments 一直和命名參數(shù)的值保持同步,arguments[0] 的改變也會引起 param 的改變。事實上,他們是同個變量的不同名稱。在 ES5 嚴(yán)格模式下,這種令人迷惑的特性被移除了:

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

這次,arguments[0] 的改變沒有影響到 param,并且輸出和期望一樣。ES6下,輸出結(jié)果和 ES5 的嚴(yán)格模式是一致的。但是請記住,在函數(shù)聲明時使用了默認(rèn)參數(shù),arguments 不受影響。

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

在這個函數(shù)中,盡管 param3 有默認(rèn)值,但他和 arguments[2] 并不相等,因為只有兩個參數(shù)傳入了函數(shù)。也就是說,設(shè)置默認(rèn)參數(shù)并不影響 arguments 對象。

結(jié)論

ES6 給 JavaScript 帶來了許多大大小小的改進(jìn)。越來越多的開發(fā)者開始使用 ES6,而且很多所有的特性都可以無障礙使用。本文我們學(xué)習(xí)了 ES6 是如何提升JavaScript 處理參數(shù)的能力的。但我們僅僅學(xué)了 ES6 的一點皮毛。更多的有趣的特性等著我們?nèi)ネ诰?#xff01;

  • ECMAScript 6 Compatibility Table, Juriy Zaytsev

  • “ECMAScript 2015 Language Specification,” ECMA International


看下時間現(xiàn)在正好是23:23,幾乎用了一個下午和晚上把這篇文章讀完又翻譯完,這篇文章結(jié)合 ES5 和 ES6 來講解,收益頗多。不過翻譯水平有限,求多提意見多多指教 ~

原文地址: How To Use Arguments And Parameters In ECMAScript 6

小廣告

歡迎關(guān)注我們的微信公眾號:

總結(jié)

以上是生活随笔為你收集整理的如何使用ES6中的参数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。