パラメータ 関数パラメータは、関数定義箇所と関数呼び出し箇所の 2 か所に出現します。この 2 か所のパラメータは異なります。
仮パラメータ (仮パラメータ)
関数定義に現れるパラメータは、データを持たず、関数が呼び出されて渡されたデータを受け取るまで待機するだけであるため、仮パラメータまたは仮パラメータと呼ばれます。略してパラメータ。
実パラメータ (実パラメータ)
関数の呼び出し時に指定されるパラメータには実際のデータが含まれており、関数内のコードで使用されるため、実パラメータ、または略して実パラメータと呼ばれます。
仮パラメータと実パラメータの違いと関係
1) 仮パラメータ変数は関数の呼び出し時にのみメモリを割り当て、呼び出しが完了するとメモリはすぐに解放されるため、仮パラメータ変数は関数内でのみ有効です。機能外では使用できません。
2) 実パラメータは、定数、変数、式、関数などです。実パラメータのデータの種類に関係なく、関数呼び出しを行うときに、これらの値を仮パラメータに転送するには、特定の値が必要です。 , そのため、事前に代入や入力などのメソッドを使用して、実際のパラメータの特定の値を取得する必要があります。
3)実際のパラメーターと正式なパラメーターは、数、タイプ、および順序が厳密に一貫している必要があります。そうしないと、「タイプの不一致」エラーが発生します。もちろん、自動型変換が可能な場合や強制的に型変換を行った場合には、実パラメータの型が仮パラメータの型と異なる場合もあります。
4) 関数呼び出しで発生するデータ転送は一方向であり、実パラメータの値は仮パラメータにのみ転送できますが、仮パラメータの値を逆方向に実パラメータに転送することはできません。 ; 言い換えれば、データ転送が完了すると、実パラメータと仮パラメータは無関係になるため、関数呼び出し中に仮パラメータの値が変更されても実パラメータには影響しません。
5) 仮パラメータと実パラメータは同じ名前を持つことができますが、実パラメータは関数の外部で有効であるのに対し、仮パラメータは関数の内部で有効であるため、それらは互いに独立しており、相互に影響しません。
仮パラメータと実パラメータの機能は、関数呼び出しが発生すると、データを渡すことです。実パラメータの値は仮パラメータに渡されます。
関数を使用すると、データを渡すことができ、渡されたデータは関数の実行結果に影響し、関数がより柔軟で再利用可能になります。
関数 foo(a, b) { console.log([a, b]); } foo(1, 2); //
この出力 [1, 2] の例では、 a
とb
関数内のローカル変数であり、関数内でのみアクセスできます。関数を呼び出すと、渡されたデータが位置に応じて照合され、それぞれa
とb
に割り当てられます。
関数を作成する場合、 function 函数名
後ろに括弧内に設定されるパラメータは仮パラメータと呼ばれ、関数を呼び出す場合には、関数名の後ろに括弧内に渡されるパラメータは実パラメータと呼ばれます。上記の例では、 a
とb
仮パラメータであり、渡される1
と2
実パラメータです。
仮パラメータは宣言された変数であるため、 let
およびconst
使用して繰り返し宣言することはできません。
関数 foo(a, b) { let a = 1; // エラー、a が宣言されました const b = 1; // エラー、b が宣言されました}
JavaScript の関数転送はすべて、参照ではなく値によって渡されます。いわゆる値は、変数に直接格納された値を指します。オブジェクトがパラメータとして渡される場合、値はオブジェクト自体ではなく、オブジェクトへの参照になります。これは実際には暗黙的な割り当てプロセスであるため、パラメーターを関数に渡す場合、ある変数から別の変数に値を割り当てることと同等です。
元の値:
function add(num) { 数値 + 1 を返します。 } count = 5としましょう。 let result = add(count); // ここでパラメータを渡す処理は num = count とみなすことができます。 コンソール.log(カウント); // 5 console.log(result); // 6
参照値:
function setName(obj) { obj.name = "シャオミン"; } 人 = {} にします。 setName(person); console.log(person); // {name: "Xiao Ming"}
JavaScript の関数は、渡されるパラメータの種類も数も検出しません。関数を定義するときに 2 つの仮パラメータを設定しても、呼び出し時に 2 つのパラメータを渡す必要があるという意味ではありません。実際に呼び出すと、1つまたは3つのパラメーターが渡されても、パラメーターが渡されなくてもエラーは報告されません。
すべての関数 (矢印以外) には、 arguments
という名前の特別な配列のようなオブジェクト( Array
のインスタンスではありません) があり、これを使用して、すべての実パラメータの値を取得できます。配列値のインデックス アクセス メソッドに加えて、そのarguments.length
プロパティにアクセスして、関数が実際に呼び出されるときに渡されるパラメーターの数を決定することもできます。
例:
function foo(a, b) { console.log(引数[0]); console.log(引数[1]); console.log(arguments.length); }foo
(
10、20);
x] と同じ値です。したがって、正式なパラメーターを設定せずに関数を宣言することもできます。
関数 foo() { console.log(引数[0]); console.log(引数[1]); } foo(10、20)
;必要な数のパラメーターを渡すと、エラーが発生しません。
もう 1 つ注意すべき点は、 arguments
仮パラメータと一緒に使用でき、 arguments
オブジェクトの値は対応する仮パラメータと同期されることです。例:
function foo(a) { 引数[0]++; コンソール.ログ(a); } foo(10); // 出力 11 //---------------------------------------- 関数 foo2(a) { a++; console.log(引数[0]); }foo2
(
10);
これは、プリミティブ値を渡しているため、同じメモリ アドレスにアクセスするという意味ではありません。これらはメモリ内では依然として分離されていますが、内部メカニズムにより値は同期された状態に保たれます。
さらに、パラメータが欠落している場合、この仮パラメータの値はarguments
オブジェクト内の対応する値と同期されません。たとえば、次の例ではパラメータが 1 つだけ渡されるため、 arguments
には実際のパラメータ値が 1 つだけ存在します。このとき、関数内で argument[1] に特定の値が設定されている場合、この値は同期されません。 2 番目の仮パラメータに追加します。例:
function foo(a,b) { 引数[1] = 2; コンソール.ログ(b); } foo(1); // 出力 unknown
この例では、仮パラメータ b には実際のパラメータが渡されておらず、その値はデフォルトでundefined
になります。ただし、次の場合:
foo(1, unknown); //
出力 2 がundefined
に手動で渡されると、値undefined
を持つ要素がarguments
配列に表示されますが、この要素は引き続き b の値と同期できます。
厳密なモードでは、 arguments
オブジェクトの値と正式なパラメーターはもはや同期されなくなります。したがって、開発中にこの同期メカニズムに依存しないことが最善です。つまり、 arguments
オブジェクトに正式なパラメーターとそれらの対応する値を同時に使用しないことです。
矢印関数には引数はありません
。矢印の構文を使用して関数が定義されている場合、関数には引数はありません。
let foo = () => { console.log(引数[0]); }foo(); // エラー、引数が定義されていない
arguments
があります:
function fn1(){ let fn2 = () => { console.log(引数[0]); } fn2(); } fn1(5)。
しかし、これらのarguments
arguments
関数からではなく、矢印関数にアクセスされる場合、外部関数のarguments
見つかります。
関数に複数の仮パラメータが含まれている場合、渡されたパラメータが常に正しい位置に配置されるようにする必要があるため、関数の呼び出しが面倒になります。パラメータの受け渡し順序の制限はありますか?
オブジェクト属性は順序付けられていないため、対応する値は属性名によって決定されます。したがって、オブジェクトを渡して、オブジェクト内のプロパティを実際のパラメーターとして使用できるため、パラメーターの順序は重要ではありません。
関数 foo(obj) { console.log(obj.name, obj.sex, obj.age); } foo({ sex: ' Male', age: 18, name: ' Xiao Ming' }); // Xiao Ming は男性 18
関数呼び出し時に実際のパラメータが指定されていない場合、デフォルト値仮パラメータのうちのはundefined
です。
特定のデフォルト値を設定したい場合があります。ES6 より前では、デフォルト値の明示的な設定がサポートされていなかったときは、次の回避策を使用するしかありませんでした
。 名前 = 名前 || '全員'; console.log( 'hello' + name + '!'); } Sayhi()
false
実際のパラメーターは機能しません。
、
if
がundefined
の場合に等しいかどうかを判断できます。
if(name === undefined){ name = '全員'; } console.log( 'hello' + name + '!'); } //三項式判定関数sayHi(name) { name =(name!== undefined)? console.log( 'hello' + name + '!'); }
es6は、次のようにデフォルト値を設定する明示的な方法をサポートするため、はるかに便利です。FunctionSayhi
(name = 'Everyone'){//関数を定義する場合、値を正式なパラメータConsole.logに直接割り当てます( 'hello' + name + '!'); } Sayhi(); // 'こんにちはみんな!' Sayhi( 'Tony'); // 'Hello Tony!'Sayhi(未
undefined
);
デフォルトの値は値だけでなく、任意の法的表現でも、関数呼び出しである場合もあります:
function sayhi(name = 'Every'+'one'){ console.log( 'hello' + name + '!'); } Sayhi(); // 'こんにちはみんな!' //----------------------------------------------------- 関数 foo() { console.log( 'calling foo'); 「トニー」を返します。 } function sayhi(name = foo()){ console.log( 'hello' + name + '!'); } sayhi(); //出力 'call foo' //出力「こんにちはトニー!」 Sayhi(未定義); //出力 'call foo' //出力「こんにちはトニー!」sayhi( '
undefined
'); // hello john!
関数が定義されているときに評価されます。
パラメーターのデフォルト値の位置通常、パラメーターのデフォルト値を設定して、関数を呼び出すときにパラメーターを適切に省略できます。実際には省略することは不可能です。
関数 fn(x = 1, y) { console.log([x, y]); } fn(); //出力[1、未定義] fn(2); //出力[2、未定義] fn(、2); fn(未定義、2);
上記の例では、正式なパラメーターxに設定されたデフォルト値は意味がないようです。したがって、デフォルト値のパラメーターを最後に配置することをお勧めします。
関数 fn(x, y = 2) { console.log([x, y]); } fn(); // 出力[未定義, 2] fn(1); //出力[1, 2] fn(1, 1) //出力[1, 1]パラメータ省略問題
複数のパラメーターにデフォルト値が設定されている場合、問題は再び発生し、実際のパラメーターのみを最後のパラメーターに渡すことができません。
関数 fn(x, y = 2, z = 3) { console.log([x, y, z]); } fn(1、、10)//レポートエラー
オブジェクトを渡すことにより、パラメーター順序の制限を回避できることを以前に知っていました。パラメーターのデフォルト値を実装する方法は? ||
使用して、判断するための声明や三元if
も解決策ですが、これは少し後方に見えます。次に、ES6 の他の 2 つの新しいメソッドについて説明します。
パラメーターデフォルト値は、object.Assign()と組み合わせて使用されます
関数 fn(obj = {}) { defaultobj = { ×:未定義、 y: 2、 Z:3 } let result = Object.assign(defaultObj, obj); console.log([result.x、result.y、result.z]); } fn(); //出力[2、3] fn({x:1、z:10});
上記の例では、関数でdefaultObj
が定義され、その後、パラメーターのデフォルト値として使用されますdefaultObj のプロパティは、obj の同じ属性がオーバーライドされます。obj に他の属性がある場合、それらはdefaultObj に割り当てられます。ここでは、変数が返されたマージオブジェクトを受信するために使用されます。
同時に、正式なパラメーターobj
のデフォルト値は、 undefined
が呼び出されたときにパラメーターが渡されないようにしないように空のオブジェクトに設定されます。 、エラーが発生します。
パラメーターのデフォルト値と破壊割り当てが一緒に使用されます
関数が呼び出されると、実際のパラメーターと正式なパラメーターの一致は、実際には暗黙的な割り当てプロセスです。
関数fn({x、y = 2、z = 3}){ console.log([x、y、z]); } fn({}); //出力[2、3] fn({x:1、z:10});
この例では、オブジェクトの破壊割り当てのデフォルト値のみが使用され、関数パラメーターのデフォルト値は使用されません。関数が呼び出されたときにパラメーターが渡されない場合、エラーも報告されます。これにより、パラメーターの初期化中に破壊的な割り当てが故障します。これは、 {x, y = 2, z = 3} = undefined
などのコードの実行と同等です。 {x, y = 2, z = 3} = undefined
。
同様に、パラメーターデフォルト値の構文を使用して、 {x, y = 2, z = 3}
のデフォルトの破壊オブジェクトを設定することができます。これにより、パラメーターを渡すことなく関数をスムーズに実行できます。
関数fn({x、y = 2、z = 3} = {}){ console.log([x、y、z]); } fn(); //出力[2、3]
ここには二重のデフォルト値がありますが、これは少し混乱する可能性があります。
if(実際のパラメーター=== {...}){// fn({...}); {x、y = 2、z = 3} = {...}; } else if(実際のparameter === undefined){// fn(); {x、y = 2、z = 3} = {}; }
Double Default値に特別な注意が必要な詳細があります。これは、破壊的な割り当てのデフォルト値と、次の例を参照してください。
関数 fn ({ x = 1 } = {}, { y } = { y: 2 }){ console.log(x、y); } fn(); // 出力 1 2 fn({x:10}、{y:20}); fn({}、{});
この関数では、破壊的な割り当てを使用する2つのパラメーターがあります。渡されたパラメーターが{}
である場合、yはデフォルト値2を取得しません。これはなぜですか?前の擬似コードの例と組み合わせて:
fn({x:10}、{y:20}); // {x = 1} = {x:10}、{y} = {y:20} fn({}、{}); // {x = 1} = {}、{y} = {}
渡されたパラメーターが{}
である場合、関数パラメーターは欠落またはundefined
はないため、関数パラメーターのデフォルト値は効果がありません。同時に、 {}
の x と y には対応する値がありません。 x で得られる 1 は分割代入のデフォルト値であり、 y には分割代入のデフォルト値がないため、デフォルトはundefined
になります。 。
パラメータのデフォルト値のスコープと一時的なデッドゾーン
別の小さな詳細があります。パラメーターがデフォルト値に設定されると、独自のスコープ( (...)
に包まれます)を参照してください。
関数foo(a = b){ b = 1; } foo(); //エラーは未定義です
ただし、このスコープは一時的なものです。
また、通常のスコープのルールに従います。
b = 2 とします。 関数foo(a = b){ b = 1; を返します。 } foo();
上記の例では、グローバル変数Bがあり、その後、正式なパラメーターAはグローバル変数bの値を取得します。
もちろん、正式なパラメーター範囲に正式なパラメーターBがある場合、最初に現在の範囲が取得されます。
b = 2とします。 関数foo(b = 3、a = b){ を返します。 } foo();
複数のパラメーターのデフォルト値を設定すると、「一時的なデッドゾーン」のルールに従って、順番に初期化されます。つまり、以前のパラメーターは後のパラメーターを参照することはできません。
関数foo(a = b、b = 2){ a + b を返します。 } foo(); //エラー、初期化前にBにアクセスできません
残りのパラメーター
ES6は**残りのパラメーター(REST)**構文( ...变量名
)を提供します。これは、関数の冗長な実際のパラメーター(つまり、正式なパラメーターに対応しない実際のパラメーター)を収集できます。 arguments
オブジェクトを使用する必要があります。正式なパラメーターが...
演算子とともに使用される場合、それは配列になり、冗長な実際のパラメーターがこの配列に配置されます。
残りのパラメーターの基本的な使用法:
関数合計(a、... values){ for(値のval){ a += val; } を返します。 } sum(0、1、2、3);
上記の例では、パラメーターの初期化中に、一致がパラメーター位置に基づいて最初に実行され、0はaに割り当てられ、次に残りのパラメーター1、2、および3が配列値に配置されます。
以下は、 arguments
オブジェクトと残りのパラメーターを使用してパラメーターを取得する比較例です。
//引数関数の書き方seartnumbers(){ return array.prototype.slice.call(arguments).sort(); } //残りのパラメーターを書き込む方法const sortnumbers =(... numbers)=> { numbers.sort(); }
残りのパラメータがより簡潔に記述されていることがわかります。 arguments
配列のようなオブジェクトであり、反復可能なオブジェクトですが、結局のところ、それは配列ではありません。アレイメソッドをサポートしていません。アレイメソッドarguments
呼び出す場合は、 Array.prototype.slice.call
使用して最初に配列に変換する必要があります。
残りのパラメーターは、 arguments
オブジェクトとは異なり、配列メソッドArray
簡単に使用できます。また、矢印関数は残りのパラメーターもサポートしています。
さらに、残りのパラメーターを使用しても、 arguments
オブジェクトの機能には影響しませんが、関数を呼び出すときに渡されたパラメーターを反映できます。
残りのパラメータの位置
残りのパラメーターは最後の正式なパラメーターである必要があります。そうしないと、エラーが報告されます。
//機能FN1(a、... rest、b){ console.log([a、b、rest]); } //機能fn2(a、b、... ret)を書き込む正しい方法{ console.log([a、b、rest]); } fn2(1、2、3、4)//出力[1、2、[3、4]]
構文を展開します
以前は、冗長なパラメーターを配列に収集する方法を知っていましたが、アレイ内の要素をアレイに個別に渡すのではなく、アレイに個別に渡すなど、反対を行う必要がある場合があります。
関数合計(...値){ 合計 = 0 とします。 for(値のval){ sum += val; } 合計を返します。 } ret arr = [1、2、3、4]; sum(arr); // "01,2,3,4"
上記の例の関数は、渡されたすべての値を蓄積します。アレイに直接渡すと、必要な結果が得られません。
この例では、配列が渡されると、値の値が[[1, 2, 3, 4]]
になり、配列値に1つの要素のみになり、この要素のタイプは配列です。 。次に、値0
と[1, 2, 3, 4]
つのタイプが暗黙的に変換された結果です。
アレイを分解して関数に渡すために、パラメーターを1つずつ渡すことは不可能ですsum(arr[0], arr[1], arr[2], arr[3]);
アレイにある要素がいくつあるかを常に知っているとは限りません。アレイには多くの要素が存在する可能性があります。
Apply()メソッドを使用する方が可能です。
sum.apply(null、arr);
しかし、これはまだ最適なソリューションではないので、ここに重要なポイントがあります!
ES6の新しい**拡張構文(スプレッド)**は、この状況に直面するのに役立ちます。また...变量名
構文と同じですが、その目的は完全に反対です。
関数が呼び出されると、そのアプリケーションは次のとおりです。
sum(... arr); //合計(1,2,3,4)に相当します。
それは自由に通常の値で使用することさえできます。フロントとリアの位置に制限はなく、複数の反復可能なオブジェクトを同時に渡すことができます。
sum(-1、... arr); sum(... arr、5); sum(-1, ...arr, 5); // 14 sum(-1、... arr、... [5、6、7]);
拡張演算子は...
当社のために手動で渡すパラメーターの動作を個別に完了することに相当します。
上記の例はすべてアレイ用ですが、拡張構文はそれ以上のものを行うことができます
正式なパラメーターは、関数に渡された実際のパラメーターが正式なパラメーターに割り当てられることです。
正式なパラメーターと実際のパラメーターの数は等しくない場合があります。
●実際のパラメーターが欠落している正式なパラメーターは、デフォルト値をundefined
します。
●追加の実際のパラメーターは、矢印関数を除き、 arguments
オブジェクトからアクセスできます。
パラメーターを渡す順序がもはや重要でないように、オブジェクトを渡すことができ、オブジェクト内のプロパティを実際のパラメーターとして使用できます。
ES6のパラメーターデフォルト値 - デフォルト値は、関数が呼び出されたときにパラメーター値が欠落またはundefined
場合にのみ取得されます。
●デフォルト値を設定するパラメーターは、最後の位置に配置された場合にのみ省略できます。
● 仮引数設定のデフォルト値は関数本体内の変数を参照できませんが、以前の仮引数や外部変数は参照できます。
●Object.Assign()または破壊的な割り当てを介してデフォルト値を実装すると、パラメーターを渡す方法がより柔軟になります。
残りのパラメータとarguments
の主な違いは次のとおりです。
● 残りのパラメータには、対応する仮パラメータを持たない実パラメータのみが含まれますが、 arguments
オブジェクトには関数に渡されるすべての実パラメータが含まれます。
●残りのパラメーターは実際のArray
インスタンスですが、 arguments
単なる配列のようなオブジェクトです。
残りのパラメーターと拡張構文の両方が、機能関連のシナリオで...
演算子を使用します。
● 関数パラメータリストの最後に表示され、残りのパラメータです。
●関数呼び出しで発生し、拡張構文です。
上記は、JavaScript機能のパラメーターの詳細を説明する記事です。詳細については、PHP Chinese Webサイトの他の記事に注意してください。