JavaScriptパラメータの配列展開[訳]

5423 ワード

本文では、ECMAScript 6の知識点を説明します.ES 5さえ知らないなら、あなたはもう遅れています.CSS 4、HTML 6、ES 7 ES 8まで計画を立てています.早く形を変えてください.そうしないと淘汰します.
いくつかの場合は、1つの配列を複数の要素に展開し、これらの要素を関数として呼び出すパラメータが必要です.JavaScriptでは、Funtion.prototype.appyを使用してこのような展開操作を行うことができますが、コンストラクタを実行する場合には適用できません.ここでは、どのような展開操作とnew演算子を使用するかを説明します.1.展開します.(Spreading)
展開とは、関数の呼び出しや方法の呼び出し、またはコンストラクションを実行する際に必要なパラメータを一つの配列で提供するという意味です.Pythonでは、この操作をunpackingといいます.ECMAScript.nextにすでにあります.spread operator(プレフィックスという意味です.)この展開操作を実行します.現在のJavaScriptでは、Function.prototype.apply方法で同じ効果を実現できます.
操作子を展開するときは、実際に参加した位置に加えて、配列を展開し、形の位置に残りのパラメータを表示します.翻訳したMDN文書の残りのパラメータ2を参照してください.展開関数パラメータMath.max()メソッドは、その0からいくつかの数値タイプのパラメータの中の最大値を返します.オペレータが展開しています.パラメータとしては、直接1つの配列を使ってください.Math...[13,7,30]これは次のような書き方です.
 
  
Math.max(13, 7, 30)
現在のJavaScriptでは、アプリを使用してもいいです.
 
  
> Math.max.apply(null, [13, 7, 30])
30
apply方法の役割は以下のような呼び方を使うことです.
 
  
func.apply(thisValue, [param1, param2, ...])
この代わりに
 
  
thisValue.func(param1, param2, ...)
注意したいのは、funcは必ずしもthisValueに属する方法ではないので、applyはこの方法を一時的に持つことができます.
3.コンストラクタを展開するパラメータDateコンストラクタは、いくつかの数値タイプのパラメータを受け取り、Dateオブジェクトを生成します.オペレータを展開することによって、直接に一つの配列に入ることができます.
 
  
new Date(...[2011, 11, 24]) // 2011
しかし、今回はappy方法を使って、newと一緒に仕事ができません.
 
  
> new Date.apply(null, [2011, 11, 24])
TypeError: function apply() { [native code] } is not a constructor
new演算子は、Date.applyが構造関数であることを望んでいます.たとえ小さい括弧でこの表現をまとめたとしても、根本的な問題はやはりあります.appyは関数呼び出しを実行しています.パラメータをnew演算子に渡すことができません.
3.1解決方法
第一歩.まず結果を正しいものにして、後で分割したパラメータの代わりに配列をどうやって使うかを考えます.
 
  
new (Date.bind(null, 2011, 11, 24))
まずbind()を使ってパラメータなしの関数を作成します.(パラメータはこのバインディング関数の内部に結合されています.)そしてnewを使って呼び出します.普通のコンストラクターを呼び出すように.bindの関数署名は以下の通りです.
 
  
func.bind(thisValue, arg1, arg2, ...)
bind関数は元の関数を返します.
funcは新しい関数に変わりました.この新しい関数のです.
this値は常にパラメータです.
thisValueで指定された値には、arg 1から最後までのすべてのパラメータが含まれています.この新しい関数を呼び出すと、既存の通過に従う新しいパラメータが追加されます.
bindバインディングのパラメータの後ろに.MDNにはより詳細な資料があります.上記の例では、最初のパラメータは
nullです
Date関数は必要ありません.
thisValue:構造関数として呼び出された時、
new演算子は、bindで指定されたtを上書きします.
hisValue.
第二のステップ.配列をbindに転送したいです.だからもう一度applyを使って、一つの配列を展開のパラメータに変換してbind関数に伝達します.
 
  
new (Function.prototype.bind.apply(
Date, [null].concat([2011, 11, 24])))
私たちは関数Funtions.prototype.bindでapplyメソッドを呼び出します.二つのパラメータがあります.
•最初のパラメータ:thisの値はDateと指定されています.つまり、上記のDate.bind(...)に相当します.
•2番目のパラメータ:bindメソッドに渡すパラメータ、nullと後ろの配列[2011,11,24]が接続された新しい配列.
3.2ライブラリ関数
Mozillaは上記の作業を倉庫に入れる方法を提案しています.以下のコードはまさにそれらの提案の上で少し修正しました.
 
  
if (!Function.prototype.construct) {
Function.prototype.construct = function(argArray) {
if (! Array.isArray(argArray)) {
throw new TypeError("Argument must be an array");
}
var constr = this;
var nullaryFunc = Function.prototype.bind.apply(
constr, [null].concat(argArray));
return new nullaryFunc();
};
}
実行してください:
 
  
> Date.construct([2011, 11, 24])
Sat Dec 24 2011 00:00:00 GMT+0100 (CET)
3.3より簡単に見える解決策
new演算子の操作は手動で行うことができます.例えば、
 
  
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は普通の関数として呼び出され、構成関数として呼び出されるのと同じです.コールオフ()とappy()の方法で最初のパラメータで指定されたthis値を無視して、常に生成して新しいインスタンスに戻ります.
ここで著者が勘違いしているのは、Dateが普通の関数として呼び出すのと構成関数として呼び出されるのとは全く違っています.newを使わない場合、パラメータがあるかどうかに関わらず、Dateは現在の時間の文字列だけに戻ります.つまり、toString()です.
 
  
> Date.construct([2011, 11, 24])
{}
内蔵されているコンストラクションでは、Aray()、Function()、RegExp()、Errror()などのコンストラクターが呼び出された時に、newを入れないか、ほとんど同じではないです.例えば、Aray(10)も一つの配列を生成しますが、Number()、Stering()、Boolean()は同じではありません.newを加えないと元のタイプに戻す関数です.
 
  
>typeof Number("1")
"number"
>typeof new Number("1")
"object"
あなたが見ているように、Dateメソッドを操作する時、私達が書いたこのconstruct()方法は予定通りに動作できません.また他にもいくつかの内蔵構造関数もDateと同じ表現があります.ただし、一つのライブラリを操作する時に、ユーザー定義の構造関数を操作する時、この方法は基本的に正常に動作します.(一部のコンストラクタは、デフォルトの自動生成のインスタンスthisを返すのではなく、自分で指定したオブジェクトの値を返します.)
一つのコンストラクションのreturn文は、オブジェクトの値を返すと、デフォルトのthis値が上書きされます.たとえば、
 
  
function Func1(){
   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"}