JavaScript Thisに対する理解を深める
5323 ワード
私のブログへようこそ.「JavaScript Thisに対する理解を深める」
JavaScriptに関する
最近『You Dotent Know JS』という本を読んでいますが、JSの長年の先端を使ってこの本を読んでも、多くの収穫があると思います.
まず皆がよく知っている言葉があります.私はもう一度強調します.「
この文はとても重要で、これは
「語法作用域」と「動態作用域」
通常、作用域は全部で二つの主要な作業モデルがあります.語法の作用領域 ダイナミックスコープ 語法のスコープはほとんどのプログラミング言語で採用されているモードですが、ダイナミックスコープではまだいくつかのプログラミング言語が使用されています.例えば、Bashスクリプトです.JavaScriptは採用された語法の作用域であり、つまりプログラミング段階では、役割領域が明確になってきています.
次のコードを考える:
JavaScriptが採用されているダイナミックレンジである場合、
thisの4つの結合規則
JavaScriptでは、thisの指向に影響を与えるバインディングルールは4つあります.デフォルトバインディング 暗黙的バインディング 明示バインディング newバインディング 標準バインディング
これは最も直接的な方法です.つまり、修繕符をつけないで直接関数を呼び出すことです.
陰式バインディング
この場合は呼び出し位置に「コンテキストオブジェクト」がある場合に発生します.
明示的なバインディング
このように、
次のコードを考える:
newバインディング
最後の一つは、新しいオブジェクトを作成します. この新しいオブジェクトは[Prottype]接続されます. この新しいオブジェクトは、関数呼び出しのthisに結合されます. 関数が他のオブジェクトに戻っていない場合、new式の関数呼び出しは自動的にこの新しいオブジェクトに戻ります. したがって、
優先度
一つの位置にthisを変更するルールが複数発生した場合、優先度はどうなりますか?
いくつかのコードを見ます
「newバインディング」>「明示バインディング」>「陰式バインディング」>「標準バインディング」
だから、thisは一体何ですか?
参照
You Dott Know JS-this&Object Prottotypes
JavaScriptに関する
this
の話はもうたくさん見たと思います.注文した以上、続けて見てもいいです.this
に対する理解を深めてくれますか?最近『You Dotent Know JS』という本を読んでいますが、JSの長年の先端を使ってこの本を読んでも、多くの収穫があると思います.
this
についての説明は、私の理解を深めてくれました.知識点を整理し、自分の理解を加えて、自分の言語で説明します.読者にとっては中古の知識です.この本はオープンソースです.本書のGithubプロジェクトの住所に行って、片手の知識を学ぶことができます.まず皆がよく知っている言葉があります.私はもう一度強調します.「
this
は関数が呼び出された時に発生したバインディングです.何を指すかは関数がどこで呼び出されるかによって決まります.」この文はとても重要で、これは
this
の原理を理解する基礎です.this
を説明する前に、作用域に関する概念を理解しておく必要があります.「語法作用域」と「動態作用域」
通常、作用域は全部で二つの主要な作業モデルがあります.
次のコードを考える:
function foo(){
console.log(a); // 2
}
function bar(){
let a = 3;
foo();
}
let a = 2;
bar()
JavaScriptが使用するのは語法作用領域であるため、自然this
が宣言した段階では、変数foo()
の作用領域が確定されている.JavaScriptが採用されているダイナミックレンジである場合、
a
において印刷されたものはfoo()
である.function foo(){
console.log(a); // 3 ( 2)
}
function bar(){
let a = 3;
foo();
}
let a = 2;
bar()
JavaScriptの3
は、動作時に呼び出された場所で動的に結合された動的スコープと似ている.thisの4つの結合規則
JavaScriptでは、thisの指向に影響を与えるバインディングルールは4つあります.
これは最も直接的な方法です.つまり、修繕符をつけないで直接関数を呼び出すことです.
function foo() {
console.log(this.a) // a
}
var a = 2; //
foo();
this
を使用して宣言された変数var
は、グローバルオブジェクトに紐付けられ、ブラウザであればa
オブジェクトである.window
が呼び出したとき、デフォルトのバインディングを参照して、foo()
はグローバルオブジェクトを指す.陰式バインディング
この場合は呼び出し位置に「コンテキストオブジェクト」がある場合に発生します.
function foo() {
console.log(this.a);
}
let obj1 = {
a: 1,
foo,
};
let obj2 = {
a: 2,
foo,
}
obj1.foo(); // 1
obj2.foo(); // 2
関数が起動されると、コンテキストオブジェクトがある場合、this
は、コンテキストオブジェクトにバインドされる.上記のコードのように、this
が呼び出されたとき、obj1.foo()
はthis
にバインドされ、obj1
が呼び出されたとき、obj2.foo()
はthis
にバインドされている.明示的なバインディング
このように、
obj2
の3つの方法Function.prototype
、call()
、apply()
を使用している.これらの3つの関数は、関数のbind()
が指定されたオブジェクトに向けられていてもよく、違いは、this
およびcall()
が即座に関数を実行し、許容されるパラメータの形式が異なることである.apply()
call(this, arg1, arg2, ...)
apply(this, [arg1, arg2, ...])
は、新しい包装関数を作成し、すぐに実行するのではなく、リターンする.bind()
bind(this, arg1, arg2, ...)
は、パラメータの形式を受信し、関数ネスティング関数を容易にすると、apply()
変数を次の階層関数に伝達する.次のコードを考える:
function foo() {
console.log(this.a); // 1
bar.apply({a: 2}, arguments);
}
function bar(b) {
console.log(this.a + b); // 5
}
var a = 1;
foo(3);
上記のコードでは、arguments
内部のfoo()
は、デフォルトのバインディング規則に従い、グローバル変数にバインディングされている.this
は、呼び出し時にbar()
関数を呼び出し、apply()
を新しいオブジェクトthis
に結び付け、そのまま受信した{a: 2}
の関数です.newバインディング
最後の一つは、
foo()
オペレータを使用してnew
のバインディングを生成することである.this
オペレータのnew
に対する影響を理解するには、まずthis
の原理を理解する必要がある.JavaScriptでは、new
オペレータは、他の対象言語とは違って、アナログされたメカニズムである.JavaScriptでは、すべての関数をnew
で呼び出すことができます.このとき、この関数は一般的に「構造関数」と呼ばれます.実際にはいわゆる「構造関数」は存在しません.より正確な理解は、関数に対する「構造呼び出し」です.new
を使用して関数を呼び出すと、自動的に以下の動作が実行されます.new
が関数であれば、このようになります.function New(Constructor, ...args){
let obj = {}; //
Object.setPrototypeOf(obj, Constructor.prototype); //
return Constructor.apply(obj, args) || obj; // , this
}
function Foo(a){
this.a = a;
}
New(Foo, 1); // Foo { a: 1 }
したがって、new
を使用して関数を呼び出すと、新しいオブジェクトを構築し、関数呼び出しのnew
に結合します.優先度
一つの位置にthisを変更するルールが複数発生した場合、優先度はどうなりますか?
いくつかのコードを見ます
// >
function foo() {
console.log(this.a);
}
let obj1 = {
a: 2,
foo,
}
obj1.foo(); // 2
obj1.foo.call({a: 1}); // 1
これは「明示的バインディング」の優先度が「暗黙的バインディング」より大きいことを示しています.// new >
function foo(a) {
this.a = a;
}
let obj1 = {};
let bar = foo.bind(obj1);
bar(2);
console.log(obj1); // {a:2}
let obj2 = new bar(3);
console.log(obj1); // {a:2}
console.log(obj2); // foo { a: 3 }
これは「newバインディング」の優先度が「明示的バインディング」よりも大きく、「デフォルトバインディング」の優先度が最も低いことを示している.優先順位は以下の通りです.「newバインディング」>「明示バインディング」>「陰式バインディング」>「標準バインディング」
だから、thisは一体何ですか?
this
は、作成時にバインディングされたものではなく、実行時にバインディングされたものである.そのコンテキストは、関数呼び出し時の様々な条件に依存します.this
のバインディングと関数宣言の位置は関係なく、関数の呼び出しに依存します.関数が呼び出されると、「実行コンテキスト」が作成されます.このコンテキストは、関数がどこで呼び出されるか(コールスタック)、関数の呼び出し方法、着信するパラメータなどの情報を含みます.this
は、この記録の属性の一つであり、関数実行中に使用される.参照
You Dott Know JS-this&Object Prottotypes