この点は js が比較的わかりにくい点でもあり、これが誰を指しているのかを間違えやすいことがあります。
重要なポイントは 2 つあります
。 1. これは常に現在の実行環境として実行されます。
2. この点は、関数の呼び出し方法によって異なります。
グローバル実行コンテキスト内。
console.log(this == window); // true
var b = 20;
console.log(window.b); //20
this.add = (a,b) =>{
return a+b
}
window.add(5,5) //10
上記のコードからわかります。グローバル var == this. == window.; 内
関数コンテキスト。
関数の呼び出し方法によって異なります。
グローバルで直接呼び出される
function foo(){
return this;
}
console.log(foo() == window) //true
これは引き続き、call、apply を呼び出すオブジェクトにバインドされたウィンドウを指します。
let obj = {
name:'lly',
age:20,
}
function gud(){
return this.name+':'+this.age
}
console.log(gud.call(obj)) //lly:20
console.log(gud.apply(obj)) //lly:20
呼び出して適用し、ウィンドウを指すように、オブジェクト obj コンストラクターで使用されるように、this のポインティングを変更します。
function myobj(name,age){
this.name = name;
this.age = age;
this.say = function(){
return `我叫${
this.name},今年${
this.age}`
}
}
let lly = new myobj('lly',22);
console.log(lly.say) //我叫lly,今年22
コンストラクターは、現在の新しいオブジェクトを指します。
新規作成の手順
1. 空のオブジェクトを作成します。
2. これをこの空のオブジェクトにポイントします。
3. プロパティとメソッドを割り当てます。
4. これを返します。
オブジェクトメソッドで使用される
let obj ={
name:'lly',
age:40,
says:function(){
return this.name+':'+this.age
}
}
console.log(obj.says()) // lly:40
関数が呼び出されると、現在の関数を指すことになるため、オブジェクト内の関数がアロー関数に置き換えられたらどうなるでしょうか。
var name = '全局';
var age=20;
let obj ={
name:'lly',
age:40,
says:() =>{
return this.name+':'+this.age
}
}
console.log(obj.says()) //全局:20
アロー関数自体にはこれがないため、これが再びグローバルを指していることが魔法のようにわかります。
Dom ノードで使用する
$('.btn').click(function(){
console.log(this);
})
document.getElementById('btn').onclick = function(){
console.log(this);
}
<button onclick="console.log(this);">点我</button>
これは DOM 要素ノードを指します。
まとめ
this の方向と this の方向を判定するのは関数を呼び出した時点で決まり、
順序に従って
アロー関数かどうかを判定することができます。
ポインタを変更する動作があるかどうかを判断し、apply binding を呼び出して、ポインタが
配置されている実行コンテキストを判断します。
------------------------ 手動セグメンテーション -----------------------------------
知らないjsを読んだ後、記録を作成し、記録の伸びを比較します。
このバインディングのいくつかのルール
1. デフォルトのバインディング
function wait(){
console.log(this.a);
}
var a = 2;
wait(); // 2
上記のコードの this はグローバル変数 a を指し、デフォルトのバインディングは this をグローバル オブジェクトにバインドするため、グローバル オブジェクトを指します。前述の呼び出しの場所に応じて、呼び出しの場所はグローバル コンテキストで呼び出されるため、ここからわかります。
注意すべき点は、厳密モードでは、wait() が呼び出される場所とは何の関係もないことです。
2. 暗黙的なバインディング
function add(){
console.log(this.a+this.b);
}
let objs = {
a:1,
b:2,
add:add
}
objs.add(); // 打印 3
上記では、オブジェクト obj のプロパティへの add メソッドを参照によって参照していることがわかりますが、
objs.add を通じてこのメソッドを呼び出すと、これが objs を指していることがわかります。これは暗黙的なバインディングです。
**暗黙的な損失: **暗黙的なバインディングを使用する場合、暗黙的なバインディングとして失われる可能性があります。
function add(){
console.log(this.a);
}
let objs = {
a:10,
add:add
}
let objd = objs.add;
objs.add(); // 10
objd(); // undefined
objs に暗黙的にバインドされているものは単なる参照であり、再度使用されても参照のままです。これを持たないバインディングはデフォルトのバインディングになります。したがって、それは未定義です。
3. 明示的バインディング (ハード バインディング)
これは、this の方向を変更するために前述した 2 つの呼び出しと適用でもあり、このメソッドによって this の方向が変更されたことがわかるため、明示的バインディングと呼ばれます。
function add(){
console.log(this.x+this.y);
}
let objs = {
x:1,
y:2
}
add.apply(objs) //3
これについては上でも触れましたので、簡単に説明しましょう。[適用] は、objs への追加ポイントを変更します。残念ながら、明示的なバインディングでは、以前に提起したバインディングの欠落の問題はまだ解決されていません。
ハードバインディングのバインド方法
function add(y){
console.log(this.x + y);
}
let objs = {
x:5
}
let bar = add.bind(objs);
bar(10); //15
bind(…) は、引数を this コンテキストとして設定し、元の関数を呼び出すハードコーディングされた新しい関数を返します。
4.新しいものを新しいものにバインドするプロセスこれの途中に修正の手順が半分あること
は皆さんご存知だと思います。
function foo(a) {
this.a = a;
}
var bar = new foo(2);
console.log( bar.a ); // 2
new で foo(…) を呼び出すと、新しいオブジェクトを構築し、 foo(…) 呼び出しでこれにバインドします
。new は、関数が呼び出されたときにこのバインディングの動作に影響を与えることができる最後のメソッドであり、これを新しいバインディングと呼びます。
実行中の関数の this バインディングを確認したい場合は、この関数の直接呼び出しの場所を見つける必要があります。それを見つけた後、
次の 4 つのルールを順番に適用して、このバインディング オブジェクトを決定できます。
- 新しい人に呼ばれましたか?新しく作成したオブジェクトにバインドします。
- コールまたは適用 (またはバインド) によって呼び出されますか? 指定されたオブジェクトにバインドします。
- コンテキストオブジェクトによって呼び出される? そのコンテキスト オブジェクトにバインドします。
- デフォルト: 厳密モードでは未定義にバインドします。それ以外の場合はグローバル オブジェクトにバインドします。