首頁 > web前端 > js教程 > 主體

JavaScript 參數中的陣列展開 [譯]_javascript技巧

WBOY
發布: 2016-05-16 17:49:41
原創
1441 人瀏覽過

譯者註:本文要講的是ECMAScript 6中的知識點,如果你連ES5都不了解的話.我得說,你已經很落後了.CSS4,HTML6,甚至ES7 ES8都已經開始規劃了,趕緊形動起來吧,否則淘汰!

有些時候,我們需要把一個數組展開成多個元素,然後把這些元素作為函數調用的參數.JavaScript中可以使用Function.prototype.apply來實現這種展開操作,但它不能被應用在執行建構函式的情況下.本文解釋了什麼是展開操作以及如何在使用new運算子的同時進行展開操作.

1.展開(Spreading)

展開的意思是在一個函數呼叫或方法調用中,或者執行一個構造函數時,通過一個數組來提供所需的參數.在Python中,這種操作稱之為unpacking . ECMAScript.next中已經有了(展開操作符)spread operator (表示為一個前綴...)來執行這個展開操作.在目前的JavaScript中,你可以透過Function.prototype.apply方法來實現相同的效果.

譯者註:展開操作符除了能用在實參的位置,把數組展開,還可以用在形參的位置,表示剩餘參數.請看我翻譯的MDN文檔剩餘參數

2.展開函數參數

Math.max()方法返回它的0到若干個數值類型的參數中的最大值.有了展開操作符,你可以直接使用一個陣列來作為參數:

Math.max(...[13, 7, 30])
這等同於下面的寫法

複製程式碼 程式碼如下:

Math.max(13, 7, 30)







複製代碼


代碼如下:


> Math.max.apply(null, [13, 7, 30])
複製程式碼

程式碼如下:


func.apply(thisValue, [param1, param2, ...])
來取代這種

複製程式碼 程式碼如下:
.func(param1, param2, ...)


要注意的是,func不一定是屬於thisValue的方法,apply可以讓它暫時擁有這個方法.


3.展開建構子的參數複製程式碼


程式碼如下:

new Date(...[2011, 11, 24]) / / 2011年的聖誕夜

但是,這次我們不能使用apply方法來實現展開操作,因為它不能與new一起工作:


複製程式碼 程式碼如下: > new Date.apply(null, [2011, 11, 24])
TypeError: { [native code] } is not a constructor


new運算子希望Date.apply是個建構子.就算你用小括號將這個表達式括起來,根本問題還是存在:apply執行的是函數呼叫,它不能將參數傳遞給new運算子.
3.1 解 第一步. 我們先讓結果變的正確,稍候再考慮怎麼用陣列取代分割開的參數. 複製程式碼 程式碼如下: 程式碼如下: new (Date.bind(null, 2011, 11, 24))
我們先用bind()來創建一個無參數的函數(參數已經綁定在這個綁定函數的內部了),然後使用new調用它,就像調用一個普通的構造函數一樣.bind的函數簽章如下:
複製程式碼 程式碼如下:

func.bind(thisValueValue, arg1,
func.bind(thisValueValue, arg1, 32 , ...)
bind函數將原函數func轉變成一個全新的函數,這個全新函數的this值永遠是參數thisValue指定的值,並且它的初始參數包含了從arg1開始到最後的所有參數.當調用這個新函數時,新添加的參數會跟隨在那些已有的通過bind綁定的參數後面.MDN上有更詳細的資料.注意上面的例子中,第一個參數是null,因為Date函數並不需要一個thisValue:在作為建構子呼叫時,new運算子會覆寫掉透過bind指定的thisValue

. 第二步.我們想把數組傳給bind.所以再次使用了
apply,將一個數組轉換為展開的參數傳遞給bind函數
.

複製程式碼
程式碼如下:

new (Function.protype.bunction.protype.bunction.protype.bunction. .apply(
Date, [null].concat([2011, 11, 24])))



我們在函數Function.prototype.bind上呼叫apply,方法帶有兩個參數:

•第一個參數: this的值指定為Date, 也就相當於上面寫的的Date.bind(...).
•第二個參數:傳給bind方法的參數,null與後面的陣列[2011, 11, 24]連接成的新陣列.
3.2 一個函式庫函數

Mozilla建議將上述工作封裝成一個函式庫方法.下面的程式碼正是在它們的建議

之上稍微修改了一下:

程式碼如下:


if (!Function.prototype.construct) {

if (!Function.prototype.construct) {
>Function.prototype.construct = function(argArray) {
if (! Array.isArray(argArray)) {
throw new TypeError("Argument must be an array");
}
var
var constr = this;
var nullaryFunc = Function.prototype.bind.apply(
constr, [null].concat(argArray));
return new nullaryFunc();
};
return new nullaryFunc();

複製程式碼

程式碼如下:


程式碼如下:> Date.construct([2011, 11, 24])

複製代碼

代碼如下:
var foo = new Foo("abc"); 實際上等同於:

複製代碼

程式碼如下:

var foo = Object.create(Foo.prototype); Foo.call(foo, "abc"); 根據這個原理,我們可以寫一個簡單的函式庫方法:

複製程式碼


程式碼如下:


程式碼如下: 程式碼如下: Function.prototype.construct = function(argArray) { var constr = this; var inst = Object.create(constr.prototype); constr.apply(inst, argArray); ; return inst; };
唉!Date作為一個普通函數來調用和作為一個構造函數來調用是一樣的:它會忽略掉call()和apply()方法中第一個參數指定的this值,總是會生成並返回一個新的實例.

譯者註:這裡作者理解錯了,Date作為普通函數調用和作為構造函數來調用是完全不一樣的.不加new的情況下,無論有沒有參數, Date()只會傳回目前時間的字串,也就是(new Date()).toString()
複製程式碼程式碼如下:

> Date.construct([2011, 11, 24])
{}

譯者註:內建的建構子中註: (),Function(),RegExp(),Error()等建構子在呼叫時,加new或不加幾乎一樣.例如Array(10)也是產生一個陣列,但Number(),String(),Boolean( )就不一樣了.不加new它們是型別轉換函數,回傳的是原始值,加new是建構子,回傳的是物件值.
複製程式碼 程式碼如下:

>typeof Number("1")
"number"
>typeof new Number("1")
"object"

正如你所看到的,在操作Date()方法時,我們所寫的這個construct()方法並不能如期工作,而且還有一些其他的內置構造函數也表現的和Date一樣.不過如果是在操作一個庫中自定義的構造函數的時候,這個方法基本上可以正常工作(少部分構造函數返回了自己指定的對象值,而不是返回了默認的自動生成的實例this).

譯者註:一個建構函數的return語句只要回傳的是個物件值,就會覆寫預設的this值.例如:
複製程式碼 程式碼如下:

function Func1(){
   this.value = "this"; return {}
   this.value = "this"; return {}
 㟜>}

function Func2(){
this.value = "this"; return 1}function Func3(){ this.value = "this";}>new Func1() //回傳的{}是個物件值,覆寫了預設的this.{}>new Func2() //回傳的1是個原始值,所以仍然傳回預設的this.{value:"this"}>new Func3() //沒有return語句,預設回傳了undefined,是個原始值,所以仍然回傳預設的this.{value:"this"}>new Func3 //沒有參數時,小括號可以省略.{value:"this"}
相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板