ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript のヒョウを垣間見る: 仮パラメータと実際のパラメータの簡単な分析_JavaScript スキル

JavaScript のヒョウを垣間見る: 仮パラメータと実際のパラメータの簡単な分析_JavaScript スキル

WBOY
WBOYオリジナル
2016-05-16 17:58:27973ブラウズ

はじめに:
今日他の人からの質問を見ました:

コードをコピーします コードは次のとおりです:

function fn(x){
x = 10;
arguments[0] = 20;
console.log(x,arguments[0])
} fn()

これについてはほとんど知らないような気がするので、試してみたほうがいいかもしれないので、具体的に分析します。
本当は言語的な観点から解析したかったのですが、残念ながら私のスキルが足りず、大まかにしか試すことができないので、ヒョウの片鱗と呼んでいます。正してください。
昨日書きましたが、今日ご飯を食べながら改めて考えましたが、まだ信頼できないところがあったので、もう一度見直してみました。
すべての JS 入門書には、JS 関数内に Arguments オブジェクトの引数があることが記載されています。これは、関数の呼び出し時に実際に関数のパラメーターを渡すために使用されます。fn.length は仮パラメーターの長さを保存します。
これらは分析に少し役立ちますが、形式的なパラメータに関する詳細な情報を取得したいのですが、今のところこれより良い方法があるかどうかはわかりません。
したがって、私たちはそれをシミュレートすることしかできません。
今のところシミュレーションを無視して、実際の問題から始めます:

コードをコピーします コードは次のとおりです:
"http://www.w3.org/TR/xhtml1/DTD/xhtml1- transitional.dtd">


;

パラメータに非表示の宣言が含まれています var x = unknown
function fn(x){
console.log(x,arguments[0]);
console.log( x,arguments[0] );
}
console.log('fn():');
//未定義
//未定義 , 2
console.log ('fn(1):');
fn(1)
//1,1
//2,2


フォーカス最後の 2 つの関数 (fn_1、fn_2) では、仮パラメータに対応する x を直接再宣言しています。インターネット上で、これは宣言されたローカル変数 x であると言っている人を見かけました。
同様ですが、このローカル変数は一般的なローカル変数ではありません。関数の定義時に、関数本体内に同じ名前のローカル変数が宣言されている場合、この宣言は無視されます。同時に、関数本体にはオブジェクトの引数が存在します;
(乱文: 引数を配列として定義しなかった理由の 1 つは、実際のパラメータの数を決定できないためだと個人的には考えています)関数定義では [実行時に動的に決定される] 場合、配列が無限に大きいか、配列が値を受け取るとすぐに境界を超えます)。
トピックに戻る:
fn_2 の場合、初期化パラメータは var x と同等です (この時点では x には値が割り当てられておらず、デフォルトは未定義です。割り当てはステートメントの実行時に割り当てられます)。
次のように記述できれば、 fn_2 は次のようになります:




コードをコピーします


コードは次のとおりです。
2. 関数の構文テストに合格すると、関数内の引数オブ​​ジェクトが最初から割り当てられます。割り当てが完了すると、関数本体のステートメントが実行され始めます。
次のステートメントは私自身のものであり、正しいかどうかはわかりません (特に関連するステートメント):




コードをコピー

コードは次のとおりです。

仮パラメータ (対応する変数) に値が割り当てられていることが判明すると、引数に対応する項目があれば、その項目を検索します。 to argument が見つかったら、仮パラメータを対応する引数の関連付けの項目に設定します。対応する項目 (未定義) が引数内に見つからない場合、仮パラメータと引数は独立したままになります。ここで探しているのは、関数実行の開始時の引数のスナップショットです。同様に、引数の代入にも同じことが当てはまります。 上の削除した部分は昨日のもので、赤字の部分は書いている途中で間違っていることに気づいて追加しました。今日我に返ると、なぜ昨日はスナップショットについてあんなに愚かなことを考えたのでしょうか?これは関数の実行開始時の関連付けの直接の 判断ではないでしょうか?そこで式を変更しました:

コードをコピーします

コードは次のとおりです:

関数の実行開始時に、仮パラメータの関連情報を設定します。対応する項目 (両方とも未定義) が形状の対応する引数で見つかる場合、2 つは関連しています。後でどのように処理されても、関数本体全体の関連情報は変更されません。

したがって、次の例も変更されます:
例に戻ると、fn_2 関数の構文テストに合格し、2 番目のステップから実行が開始されます:
パラメーターなし
コードをコピーします コードは次のとおりです。

fn_2(); function
/ /arguments の割り当てが完了しました。実際のパラメータがないため、arguments パラメータのリストは空です。同時に、関連する情報が判断されますが、仮パラメータは存在し、引数は空です。
var x = 3;//x は互いに独立しています。値 3 が割り当てられます。x と argument[0] は互いに独立しています。arguments[0] はまだ未定義です。
console.log(x, argument[0]);//print x=3, argument[ 0] は未定義です
arguments[0] = 2;//引数が割り当てられ、x はarguments[0]から独立しています。したがって、x=3 は変更されません
console.log(x, argument[0]);//Print x = 3, argument[0]=2
}

パラメーター付きCase
コードをコピー コードは次のとおりです。

Case fn_2(1) パラメーター付き。
関数 fn_2(x){//引数の割り当てが完了しました。引数[0]=1。同時に、仮パラメータ x は値を持ち、この 2 つは関連しており、常に同心円になります。
var x = 3; //x には値 3 が割り当てられ、x は argument[0] に関連付けられるため、arguments[0] には値 3 が割り当てられます。
console.log(x,arguments[0]);//Print x=3, argument[0] = 3
arguments[0] = 2;//arguments[0] には値 2 が割り当てられます。なぜなら、x はすでに argument[0] に関連付けられているため、x も同時に変更されます
console.log(x, argument[0]);//Print x = 2, argument[0]=2
}

逆も同じである必要があります:
パラメータなし
コードをコピーします コードは次のとおりです。以下のように:

fn_2();
function fn_2(x){//関連しない
arguments[0] = 2;//対応する x(unknown) が見つかりません。互いに独立
console.log(x,arguments[0]);//未定義, 2
x = 3;//互いに独立、スナップショット。引数は動的に追加されますが、それらは分離できないため、パラメータを使用すると
console.log(x,arguments[0]);//3,2
}

が失敗します。
コードをコピーします コードは次のとおりです。

fn_2(1); fn_2(x) {
arguments[0] = 2;//Association
console.log(x,arguments[0]);//2, 2
x = 3;//Association
console.log (x,arguments[0]);//3,3
}

仮パラメータが 1 つしかないため、十分な説得力がない可能性があるため、ここでパラメータを増やしますそれを2つにします。
実パラメータが 1 つだけの場合:

コードをコピー コードは次のとおりです:
fn_2( 1);
function fn_2(x,y){ //引数の割り当てが完了し、arguments[0]=1、arguments[1]=未定義のため、x のみが argument[0] に関連付けられ、y が関連付けられます。はarguments[1]に関連付けられています。
console.log(x,y,arguments[0],arguments[1]); //1,unknown,1,unknown
var x = 3;値 3 が割り当てられ、x 引数[0] に関連付けられているため、引数[0] には値 3 が割り当てられます。
console.log(x,y,arguments[0],arguments[1]); //3、未定義、3、未定義
var y = 4; //y には 3, y の値が割り当てられます。と argument[1] は互いに独立しています、arguments[1] はまだ未定義です
console.log(x,y,arguments[0],arguments[1]); //3,4,3,unknown
arguments[0] = 2; //arguments[0] には値 2 が割り当てられます。x と argument[0] はすでに関連付けられているため、x は同時に変化します
console.log(x,y,arguments[ 0],arguments[1]) ; //2,4,2、未定義
arguments[1] = 5; //arguments[1] には値 5 が割り当てられ、y と argument[1] はそれぞれ独立していますそれ以外の場合、y は 4 のままです。log(x,y,arguments[0],arguments[1]); //x=2,y=4,arguments[0]=2,arguments[1]= 5
}


2 つの実際のパラメータ:


コードをコピー コードは次のとおりです。 :

fn_3(1,6);
function fn_3(x,y){ //引数の割り当てが完了しました、arguments[0]=1、arguments[1]=6、x および argument[0] ,y とarguments[1] は相互に関連しています
console.log(x,y,arguments[0],arguments[1]) //1,6,1,6
var x = 3 ; / /x には値 3 が割り当てられ、x は argument[0] に関連付けられるため、arguments[0] には値 3 が割り当てられます。
console.log(x,y,arguments[0],arguments[1]); //3, 6, 3, 6
var y = 4; //y には 3, y の値が割り当てられます。また、arguments[1] が関連付けられているため、arguments[1] には値 4 が割り当てられます。
console.log(x,y,arguments[0],arguments[1]); //3,4,3,4
arguments[0] = 2; value 2 、x と argument[0] は既に関連付けられているため、x は同時に変更されます。
console.log(x,y,arguments[0],arguments[1]); //2,4,2 ,4
arguments[1] = 5; //arguments[1] には値 5 が割り当てられます。y と argument[1] はすでに関連付けられているため、y は同時に変化します
console.log(x, y,arguments[0], argument[1]); //x=2,y=5,arguments[0]=2,arguments[1]=5
}

すべて実際にはメソッドのパラメータ情報がないため、上記は推測です。そのため、推測に基づいて小さなテストを作成しました:
以下も変更されました:
コードをコピーします コードは次のとおりです:

function _Function(){//取得された仮パラメータ リストは配列です: _args
var _args = [ ];
for(var i = 0; i < argument.length - 1; i ){
var obj = {}; >obj[arguments[i]] = 未定義;
_args.push(obj);
//this._argu = _args; var fn_body = argument[arguments.length - 1] ;
//次のメソッドは実際のparameters_引数を取得します。ここでは、_argumentsは引数オブジェクトの代わりに配列として実装されています。
this.exec = function(){
//関数の実行時、実際のパラメータ _arguments には値が割り当てられます
var _arguments = [];
for(var i = 0; i _arguments[i] = argument[i]; 🎜>}
//以下は関数本体
eval( fn_body)
}
}





コードをコピー

コードは次のとおりです: function _Function(){//取得された仮パラメータのリストは配列です: _args var _args = []; for(var i = 0; i < 引数 .length - 1; i ){ var obj = {};
obj['key'] = 引数[ i];
obj[arguments[i]] = 未定義;
_args.
//this._argu =
var fn_body = .length - 1];
//次のメソッドは実際のパラメータ _arguments を取得します。ここで、_arguments は引数オブジェクトではなく配列として実装されます
this.exec = function(){
//関数が実行されている場合、実際のパラメータ _arguments には値が割り当てられます
var _arguments = [];
for (var i = 0; i _arguments[i] = argument [i];
}
//実行の開始時に関連情報を判断します
for( var j = 0; j _args[j]["link"] = true;
}
//以下の関数本体を実行
eval(fn_body);
}


論理的に言えば、関連付けは両方とも同じオブジェクトを指しているはずですが、サンプルを分析するだけで十分です。そこまで詳しくするつもりはなかったので、関数本体で if ステートメントを使用して判断しました。
例の fn_2 を対応する形式に置き換えます:




コードをコピーします


コードは次のとおりです:
// fn_2body では、_args[i]["link " ] = true; 仮パラメータが実際のパラメータに関連付けられていることを示します
var fn_2body = ''
'_args[0][_args[0]["key"]] = 3;'
' if(_args [0]["link"]){ _arguments[0] = _args[0][_args[0]["key"]];}'
'console.log(_args[0][_args [0] ["キー"]],_arguments[0]);'
'_arguments[0] = 2;'
'if(_args[0]["link"]){ _args[0] [_args[ 0]["key"]] = _arguments[0]}'
'console.log(_args[0][_args[0]["key"]],_arguments[0]);';
var fn_2 = new _Function('x',fn_2body);



インスタンスと書き換えられた関数の関係を示す図を描き、それを変更しました。



記事の冒頭の例に戻ります:



コードをコピーします

コードは次のとおりです。次のように:


関数 fn(x){
x = 10; arguments[0] = 20; console.log(x,arguments[0]) } fn( )
明らかに、この 2 つは互いに独立しています:
x = 10, argument[0] = 20;
推測:
コードをコピー コードは次のとおりです:

function fn(x){
x = 10;
arguments[0] = 20; .log(x, argument[0])
}
fn(1)

はすべて 20,20 を出力する必要があります

コードをコピー コードは次のとおりです。
function fn(x){
arguments[0] = 20; x,arguments[0])
}
fn(1)


も 20,20


コードをコピーする必要があります コードは次のとおりです。
function fn(x){
arguments[0] = 20;
console.log(x,arguments) [0])
}
fn()


は未定義である必要があり、20
cnblogs Xiaoxi Shanzi からの原文
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。