ホームページ >ウェブフロントエンド >jsチュートリアル >これはJavaScriptでは何でしょうか? 4つの結合方法(はじめに)

これはJavaScriptでは何でしょうか? 4つの結合方法(はじめに)

青灯夜游
青灯夜游オリジナル
2018-09-21 17:19:222264ブラウズ

この章では、JavaScript でこれは何なのかを説明します。の4つの結合方法(紹介)。困っている友人は参考にしていただければ幸いです。

これは何ですか?

関数が呼び出されると、アクティビティ レコード (実行コンテキストと呼ばれることもあります) が作成されます。このレコードには、関数が呼び出された場所 (呼び出しスタック)、関数の呼び出しメソッド、渡されたパラメーターなどの情報が含まれます。これは記録された属性の 1 つで、関数の実行中に使用されます。

#これは 4 つのバインディング メソッドです

デフォルト バインディング

function foo() { 
    console.log( this.a );
}
var a = 2;
foo(); // 2

このコードの出力 2 は、次のことを示しています。これはデフォルトでグローバル オブジェクトにバインドされます。

暗黙的なバインディング

function foo() { 
    console.log( this.a );
}
var obj = { 
    a: 2,
    foo: foo 
};
obj.foo(); // 2

このコードは、関数がコンテキスト オブジェクト (context) を参照するときに、これを obj オブジェクトにバインドします。暗黙的なバインディング ルールにより、これがこのコンテキスト オブジェクトにバインドされます。

暗黙の損失問題

// 例子1111
function foo() { 
    console.log( this.a );
}
var obj = { 
    a: 2,
    foo: foo 
};
var bar = obj.foo; // 函数别名!

var a = "oops, global"; // a是全局对象的属性”

bar();  // "oops, global"
//2222
function foo() { 
    console.log( this.a );
}
var obj = { 
    a: 2,
    foo: foo 
};

var a = "oops, global"; // a是全局对象的属性

setTimeout( obj.foo, 100 ); // "oops, global

例 1111 bar は obj.foo への参照ですが、実際には foo 関数自体を参照しているため、この時点ではbar() は実際には何も変更されていない関数呼び出しであるため、デフォルトのバインディングが適用されます。例 222 では、setTimeout 関数でこのバインディングが失われます。原理は同じです。パラメータの受け渡しは暗黙的な割り当てと見なされます。

明示的バインディング

暗黙的バインディングを分析するときは、関数を指すプロパティをオブジェクト内に含めて、その関数を間接的に参照する必要があります。この属性を通じて、これを間接的 (暗黙的) にこのオブジェクトにバインドします。

それでは、オブジェクト内に関数参照を含めたくないが、オブジェクトに関数呼び出しを強制したい場合はどうすればよいでしょうか?

js を勉強したことのある人は、call、apply、bind に精通していると思います。js が提供するこれらのネイティブ メソッドは、これを明示的にバインドする方法を提供します。

function foo() { 
    console.log( this.a );
}var obj = { 
    a:2};

foo.call( obj ); // 2

foo.call(..) を通じて、呼び出し時に foo が this を obj にバインドするように強制できます。

this のバインディング オブジェクトとしてプリミティブ値 (文字列型、ブール型、または数値型) を渡すと、プリミティブ値はそのオブジェクト形式 (つまり、new String (.. )、新しいブール値(..)、または新しい数値(..))。これはよく「ボクシング」と呼ばれます。

「このバインディングの観点から見ると、call(..) と apply(..) は同じです。それらの違いは他のパラメーターに反映されていますが、ここではこれらを考慮する必要はありません。」

ハード バインディングとバインドの実装

このバインディングの 4 つの方法はすでにわかっていますが、呼び出しと適用を使用しても暗黙的な損失の問題を解決できません。次の点を考慮してください。例:

function foo() { 
    console.log( this.a );
}

var obj = { 
    a:2
};

var bar = function() {
    foo.call( obj );
};

bar(); // 2
setTimeout( bar, 100 ); // 2

bar.call(windows) //无法再修改this

を呼び出すことで、関数 bar で foo の this を強制的に指定します。その後 bar がどのように呼び出されても、このバインディングは常に obj に対して手動で foo を呼び出します。そのため、ハードという名前が付けられます。バインディング。これがバインドの起源です (ハード バインディングがより一般的に使用され、バインド メソッドが es5 で新しくなったため) ハード バインディングを通じてこれを定式化することにより、上記のコードは

...略var bar = foo.bind(obj)
bar(); // 2setTimeout( bar, 100 ); // 2

バインド ルールの優先度となり、新しいものになります。 es6 の this の機能

実行中の関数の this バインディングを特定したい場合は、関数の直接呼び出し場所を見つける必要があります。見つかったら、次の 4 つのルールを順番に適用して、このバインディング オブジェクトを決定できます。

  1. 新規から電話がありましたか?新しく作成したオブジェクトにバインドします。

  2. 呼び出しまたは適用 (またはバインド) によって呼び出されますか?指定されたオブジェクトにバインドします。

  3. #コンテキスト オブジェクトによって呼び出されますか?そのコンテキスト オブジェクトにバインドします。
  4. デフォルト: 厳密モードでは未定義にバインドされ、それ以外の場合はグローバル オブジェクトにバインドされます。

これを理解するためのいくつかの小さな例

unction showThis () {  console.log(this)
}function showStrictThis () {  'use strict'
  console.log(this)
}
showThis() // windowshowStrictThis() // undefined
最小の優先順位を持つこのオブジェクトは、デフォルトでバインドされます。

次の例について考えてみましょう:

var person = {  name: '11',
  showThis () {    return this
  }
}

person.showThis() === person  //truevar person2 = { name: '22',
  showThis () {    return person.showThis()
  }
}var person3 = { name: '33',
  showThis () {    var retrunThis = person.showThis    return retrunThis()
  }
}

person.showThis()  //personperson2.showThis()  //?person3.showThis()  //?

最初に呼び出し場所を見つける必要があります。2 には、暗黙的に person オブジェクトをバインドする return person.showThis() という文があります。は出力です。3 は return retrunThis() です。これはデフォルトでグローバルにバインドされ、window を返します。

function showThis () {  
return this
}
var person = { name: 'person' }
showThis() // window
showThis.call(p1) // person
showThis.apply(p1) // person

コンテキスト オブジェクトは明示的なバインディングによって指定されます。

function showThis () {
  return this
}
var person = { name: 'person' }

var personBind = showThis.bind(person)

personBind()   //person

var person2 = { name: 'person2' }

personBind.call(person2) //person

bind メソッドはこれを強力にバインドするため、明示的なバインドを通じてこれを切り替えることはできなくなります。

function showThis () {
  return this
}
var person = { name: 'person' }
var person2 = { name: 'person2' }

var personBind = showThis.bind(person)

personBind()    //person
new personBind()  //showThis

new はバインドよりも優先度が高いため、これをオーバーライドできます。

function foo() { 
    setTimeout(() => {        
        // 这里的this在词法上继承自foo()
        console.log( this.a ); 
    },100);
}var obj = { 
    a:2};

foo.call( obj ); // 2

アロー関数は、function キーワードを使用して定義されませんが、「fat arrow」と呼ばれる演算子 => を使用して定義されます。アロー関数は、この 4 つの標準ルールを使用しませんが、外部 (関数またはグローバル) スコープに基づいてこれを決定します。アロー関数バインディングは、新規も含めて変更できません。アロー関数については、インターネット上に詳細かつ包括的な説明がたくさんあります。ここではこれ以上の詳細はありません。

以上がこれはJavaScriptでは何でしょうか? 4つの結合方法(はじめに)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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