JavaScriptの"WHERE "と"How "機能に着目して"this "を理解する
16084 ワード
この記事では、私はどこでどのように知っているかについて話します
はい、私はトップでその奇妙な図面を行った😀
第一に、それを理解することが重要です
最初に我々がする必要があるのは、関数がどこで我々のプログラムで呼び出されたかを見つけることです.これは、グローバル実行コンテキストまたはローカル実行コンテキストのいずれかから呼び出される可能性がありますし、我々の関数のコールサイトを見つけるための唯一の方法(直接我々のコードで見ている以外)はcall stack . ここでは、スタックを見るためにコンソールで試すことができる非常に簡単な例を示します.
まず、ブラウザのコンソールに次のコードをコピーして貼り付けます.
ここで我々の機能を見つける方法を知っています
関数が呼び出されると、新しいローカル実行コンテキストが作成されます.ローカル実行コンテキストには、関数に関する情報(呼び出しスタック内の位置、引数の長さ、およびその他のものの間の情報)があります
の値
4つの異なる規則に従って、4つの異なる方法で関数を呼び出すことができます. デフォルト 暗黙の拘束 明示的結合 新しい結合 私はまた、どのように
最初の行で変数を宣言する必要があります
時
オブジェクトのコンテキストで関数を呼び出すとき
私のポイントを説明するには、次のコードを考えます.
あなたが見ることができるように
すべての関数は、3つの異なるメソッドにアクセスでき、それらを呼び出して明示的にオブジェクトを設定できます
次のコードを考えます.
call () :明示的にバインドされるオブジェクトを呼び出して受け取ります(最初のパラメータとして) apply () : call ()と同じですが、配列内で引数が渡される点が違います. bind () : call ()と似ていますが、関数を直ちに呼び出す代わりに関数を返します
との関数呼び出し
まず、新しいオブジェクトを作成して返します.好きなもの そして、最後に、新しくつくられたオブジェクトは機能のプロトタイプにリンクされます.つまり、
ちょうどリフレッシュとして、すべての機能は
この関数はどこで呼び出されましたか?
どのように機能が呼び出されましたか?
しかし、もう一つ考えることがあります.
上記の4つの規則とは異なり
イン
でも、
そして、私たちが
私が乞食において言ったように、このポストは私がYDKJS本シリーズから特に学んだものを書いています
this
与えられた関数のポイント.基本的に、これは私があなたと共有する方法です.はい、私はトップでその奇妙な図面を行った😀
第一に、それを理解することが重要です
this binding
関数が宣言されたときには定義されません.代わりに、関数が呼び出されたときに決定され、また、その関数がどのように呼び出されたかに基づいて決定されます.ステップ1:どこ
最初に我々がする必要があるのは、関数がどこで我々のプログラムで呼び出されたかを見つけることです.これは、グローバル実行コンテキストまたはローカル実行コンテキストのいずれかから呼び出される可能性がありますし、我々の関数のコールサイトを見つけるための唯一の方法(直接我々のコードで見ている以外)はcall stack . ここでは、スタックを見るためにコンソールで試すことができる非常に簡単な例を示します.
まず、ブラウザのコンソールに次のコードをコピーして貼り付けます.
function baz() {
bar()
}
function bar() {
foo()
}
function foo() {
debugger
}
baz()
次に、devToolで、ソースタブの下に、呼び出しスタックセクションの下に、関数の一覧が表示されます.このように、foo ()を確実に知ることができます.call-site
is bar ()およびbar ()call-site
と同様である.call-site
グローバル実行コンテキストです.foo (VM431:10)
bar (VM431:6)
baz (VM431:2)
(anonymous) (VM431:13)
ここで我々の機能を見つける方法を知っています
this binding
どうやって.ステップ2:どのように
関数が呼び出されると、新しいローカル実行コンテキストが作成されます.ローカル実行コンテキストには、関数に関する情報(呼び出しスタック内の位置、引数の長さ、およびその他のものの間の情報)があります
this
).の値
this
(どのオブジェクトが指しているかは、関数がどのように呼び出されるかに基づいて決定されます.4つの異なる規則に従って、4つの異なる方法で関数を呼び出すことができます.
this binding
は矢印の関数で決定される.デフォルト
var x = 20
function foo() {
console.log(this.x)
}
foo.x = 40
foo() // 20
エーdefault binding
のように通常の関数呼び出しを行いますfoo()
. インnon-strict
モードthis binding
グローバルオブジェクトを参照するstrict mode
であろうundefined
.最初の行で変数を宣言する必要があります
x
と値を代入します.閉じるこの動画はお気に入りから削除されていますwindow.x = 20
. 長い物語短い、プロパティは、グローバルオブジェクトに作成され、これが理由ですthis.x
は20です.時
foo
が呼び出されると、このようなものがフードの下で起こります.foo.call(window) // non-strict
foo.call(undefined) // strict
私たちが後で4つの規則のうちの1つでこの主題を再訪するとしても、私は簡単に説明しますcall()
ここで行う方法call()
メソッドは、オブジェクトを明示的に設定しますthis
にバインドされます.暗黙の拘束
オブジェクトのコンテキストで関数を呼び出すとき
this
はそのオブジェクトを指します.次のコードを見てみましょう.var x = 20
const myObj = {
x: 50,
foo: function() {
console.log(this.x)
}
}
myObj.foo() // 50
での匿名関数宣言をmyObj.foo
( AKメソッドは、オブジェクト内で宣言されているので)myObj
. 関数はcallable objects
, それらはコピーによって割り当てられる原始的な値とは異なり、参照(すべてのオブジェクトのように)によって割り当てられます.私のポイントを説明するには、次のコードを考えます.
var x = 20
const myObj = {
x: 50,
foo: function() {
console.log(this.x)
}
}
myObj.foo() // 50
const foo = myObj.foo
foo() // 20
宣言するときconst foo
, 同じ関数への参照を割り当てるmyObj.foo
そして、それから、単独の呼び出しをすることによってfoo
, デフォルトのバインド規則は適用されず、strict-mode
, this
はglobal object
, この場合、window
.あなたが見ることができるように
this
関数が宣言されたときには定義されていませんが、関数が起動され、その関数がどのように呼び出されたかについて最も重要なことになっています.明示的結合
すべての関数は、3つの異なるメソッドにアクセスでき、それらを呼び出して明示的にオブジェクトを設定できます
this
にバインドされます.について話していますcall()
, apply()
and bind()
メソッド.次のコードを考えます.
const obj = {
x: 'Hi there'
}
function foo(name, age) {
console.log(
`${this.x}, my name is ${name}, and I'm ${age} years old`
)
}
foo.call(obj, 'Diego', 31)
// 'Hi there, my name is Diego, and I'm 31 years old'
foo.apply(obj, ['Diego', 31])
// 'Hi there, my name is Diego, and I'm 31 years old'
const bar = foo.bind(obj, 'Diego', 31)
bar() // 'Hi there, my name is Diego, and I'm 31 years old'
それぞれのスニペットの呼び出し方法について話しましょう.this
. コンマで区切られた関数の引数も受け取ります.this
最初の引数として渡されるオブジェクトにバインドします.このスニペットでは、返された関数をconst
そして、その下で我々は呼び出しを行います.新しい結合
との関数呼び出し
new
最初のキーワードをconstructor call
. では、次のコードスニペットを考えてみましょう.function foo(name, age) {
this.name = name
this.age = age
}
const bar = new foo('Diego', 31)
console.log(
`My name is ${bar.name}, and I'm ${bar.age} years old`
)
// My name is Diego, and I'm 31 years old
我々がするときconstructor call
fooメソッドでは、次のようになります.Object.create({})
. this
は新たに作成されたオブジェクトを指します.bar
. bar
オブジェクトデリゲート[[Prototype]] / __proto__
にfoo
's prototype
オブジェクト.ちょうどリフレッシュとして、すべての機能は
prototype
オブジェクト.それは1つのプロパティだけです.constructor
, これは関数自体へのリファレンスである.foo.prototype
/*
Output:
{ constructor: ƒ foo(name, age), __proto__: Object.prototype }
*/
bar.__proto__
// or
Object.getPrototypeOf(bar)
/*
Output:
{ constructor: ƒ foo(name, age), __proto__: Object.prototype }
*/
foo.prototype === bar.__proto__ // true
foo.prototype === Object.getPrototypeOf(bar) // true
これらは、4つのルールを決定するthis binding
関数です.だから今、我々は我々がどこに知っているために自分自身を尋ねる必要がある質問を知っているthis
が指している.この関数はどこで呼び出されましたか?
どのように機能が呼び出されましたか?
矢印関数とこれ
しかし、もう一つ考えることがあります.
上記の4つの規則とは異なり
this binding
矢印の関数は親のスコープで決定される.つまり、this binding
矢印関数はコンテナ関数と同じです.var name = 'Global'
function foo() {
const bar = () => {
console.log(this.name)
}
return bar
}
const obj = {
name: 'Diego'
}
const fn = foo()
fn() // 'Global'
const fn2 = foo.call(obj)
fn2() // 'Diego'
時foo
関数は呼び出され、this
からfoo
.イン
const fn = foo()
以来foo()
呼び出しは通常の/通常の関数呼び出しで、デフォルトのバインド規則が適用されます.この場合FOOのthis
へのポイントwindow
オブジェクトを返しますstrict mode
であろうundefined
).でも、
const fn2 = foo.call(obj)
, 明示的結合ルールは適用されます.なぜなら、fooのthis
, これはobj
オブジェクト.そして、私たちが
fn2()
(返される矢印関数を呼び出す)4つの規則に従ってデフォルトのバインドであり、それらの規則を無視し、this binding
fooの呼び出しの場合、この場合obj
.最終語
私が乞食において言ったように、このポストは私がYDKJS本シリーズから特に学んだものを書いています
this & Object Prototypes
ブック・フロムKyle Simpson . 私は完全にシリーズからすべての書籍をお勧めします.Reference
この問題について(JavaScriptの"WHERE "と"How "機能に着目して"this "を理解する), 我々は、より多くの情報をここで見つけました https://dev.to/diegolepore/what-s-the-binding-of-this-424テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol