実際、これは決まり文句の問題です。これに関する多くの記事があります。実際、私はそれを理解したと思っていましたが、昨日、私はまだプロジェクト中に少し疑いがありました。 JavaScriptで毎週収集して読んだ詳細な記事について考えました(後でリンクがあり、希土類に関する中国の翻訳が添付されました)とシニアが推奨する別の記事を考えたので、私はそれらを見て、これについての私の理解は少し改善されました。
JavaScriptの「This」は動的であり、関数が宣言されたときではなく、機能が実行されるときに決定されます。すべての関数は「これ」を呼び出すことができますが、これは関数がオブジェクトに属しているかどうかは関係ありません。これに関しては、主に4つの状況があります。
1。オブジェクトとして使用される方法は呼び出されます
関数がオブジェクトと見なされる方法である場合、関数のこれはオブジェクトを指します。
var john = {firstName: "john"} function func(){alert(this.firstname + ":hi!")} john.sayhi = func john.sayhi()// this = johnここには注目に値するものがあります。オブジェクトのメソッドが使用され、変数に割り当てられると、メソッドは関数トリガーになり、これはウィンドウまたはアンダーフィッド(Strictモード)を指します。
2。関数内を呼び出します
この関数にこれがある場合、実際にはメソッドと呼ばれることを意味します。 2つの間で呼び出すことは、それをウィンドウオブジェクトとして扱うことと同等です。これはウィンドウを指します。 ES5は実際にこれを未定義であり、ブラウザのみが古い方法に従って実行されていることを規定していることは注目に値します(Chrome、Safari、およびFirefoxの最新バージョンでテストしてください。
func()function func(){alert(this)// [object window]または[object global]または種類..}これを渡すには、()は以前に参照タイプである必要があります。これは、obj.aまたはobj ['a']と同様に、他のものではありません。
ここには小さなピットもあります。オブジェクトのメソッドに関数がある場合、関数は実際に関数モードとしてトリガーされるため、これはデフォルトでウィンドウになります(厳密なモードでは未定義です)。解決策は、これを関数に結合することです。
var番号= {numbera:5、numberb:10、sum:function(){console.log(this === numbers); // => true function calculate(){//これはウィンドウであるか、Strict Mode Console.log(this === numbers)で未定義です。 // => false return this.numbera + this.numberb; } returncalculate(); }}; numbers.sum(); // => nanまたはStrict ModeでtypeRrorをスローするvar番号= {numbera:5、numberb:10、sum:function(){console.log(this === numbers); // => true function calculate(){console.log(this === numbers); // => true return this.numbera + this.numberb; } // .call()メソッドを使用してコンテキストreturn calculate.call(this); }}; numbers.sum(); // => 153。新しい電話をかけます
オブジェクトを参照する変数は、実際にオブジェクトへの参照を保存します。つまり、変数は実際に実際のデータへのポインターを保存します。
新しいキーワードを使用する場合、この変更は実際に次の手順を実行します。
this = {}を作成します。
これは、新しいものの実行中に変更される場合があり、属性とメソッドが追加されます。
これは変更されたものを返します。
function animal(name){this.name = name this.canwalk = true} var animal = new Animal( "beastie")alert(animal.name)コンストラクターがオブジェクトを返す場合、これは返されたオブジェクトを指すことに注意する必要があります。
function animal(){this.name = 'mousie'; this.age = '18'; return {name: 'godzilla'} // < - 返されます} var animal = new Animal()console.log(animal.name)// godzilla console.log(animal.age)// undefinedここでは、新しい機能を使用することを忘れないでください。そうしないと、新しい機能は作成されません。代わりに、関数を実行するだけで、関数呼び出しに相当し、実際にウィンドウを指します
function very(type、wheelscount){this.type = type; this.wheelscount = wheelscount;これを返します;} // function invocationvar car = ver( 'car'、4); car.type; // => 'car' car.wheelscount // => 4 car === window // => true4.明らかにこれを呼び出して、呼び出しを使用して適用します
これは最もJavaScriptにインスパイアされた場所です。
次のコード:
func.call(obj, arg1, arg2,...)
最初のパラメーターはこの参照オブジェクトとして使用され、その後のパラメーターは関数のパラメーターとして使用されます。解決策は、バインドを使用することです。
関数動物(タイプ、脚){this.type = type; this.legs =脚; this.loginfo = function(){console.log(this === mycat); // => true console.log( 'the' + this.type + 'has' + this.legs + '脚'); };} var mycat = new Animal( 'Cat'、4); //「猫には4本の脚があります」setimeout(mycat.loginfo.bind(mycat)、1000); // setimeout ?? var john = {firstName: "John"、Incident: "Smith"} function func(a、b){alert(this [a] + '' + this [b])} func.call(john、 'firstname'、 'rurmame')// "John Smith"適用に関しては、アレイの正方形のパラメーターを通過するだけで、他の部分は次のように同じです。
func.call(john、 'firstName'、 'surname')func.apply(john、['firstName'、 'surname'])
また、ES5のクラス継承で使用して、親コンストラクターを呼び出すこともできます。
function runner(name){console.log(このインスタンスのウサギ); // => true this.name = name; } function rabbit(name、countlegs){console.log(このinstance of rabbit); // => true //間接的に呼ばれる、親コンストラクターrunner.call(this、name); this.countlegs = countlegs; } var myrabbit = new Rabbit( 'White Rabbit'、4);ミラビット; // {name: 'White Rabbit'、Countlegs:4}5..bind()
method.apply()と.call()を比較します。どちらもすぐに関数を実行しますが、.bind()関数は、この事前指定されたものに結合して呼び出しを遅らせる新しいメソッドを返します。
.bind()メソッドの関数は、新しい関数を作成することです。実行中のコンテキストは、.bind()によって渡された最初のパラメーターであり、このプリセットを持つ関数の作成を可能にします。
var番号= {array:[3、5、10]、getNumbers:function(){return this.array; }}; //バウンドfunctionvar boundgetnumbers = numbers.getNumbers.bind(number)を作成します。 BoundgetNumbers(); // => [3、5、10] // ObjectVarから抽出メソッドsimplegetNumbers = numbers.getNumbers; SimpleGetNumbers(); // =>未定義または厳密なモードでエラーをスローする.bind()を使用する場合、.bind()は永遠のコンテキストチェーンを作成し、変更できないことに注意する必要があります。バインディング関数が.call()または.apply()を使用して他の異なるコンテキストに渡されたとしても、以前の接続のコンテキストを変更せず、リバインディングは役割を果たしません。
コンストラクターが呼び出された場合にのみ、結合関数はコンテキストを変更できますが、これは特に推奨されるアプローチではありません。
6。矢印関数
矢印関数は、独自の実行のコンテキストを作成するものではありません。これにより、これは定義時に定義される外部関数に依存します。
コンテキスト変更方法が使用されていても、矢印関数は、コンテキストを一度バインドした後に変更することはできません。
var番号= [1、2]; (function(){var get =()=> {console.log(this === numbers); // => true return this;}; console.log(this === numbers); // => true get(); // => [1、2] // arrow actions use .apply()and .call() // => [1、2] // get.bind([0])()(// => [1、2]});これは、矢印関数に静的コンテキストがあり、異なる呼び出しのために変更されないためです。したがって、メソッドを定義するために矢印関数を使用しないでください
関数期間(時間、分){this.hours = hours; this.minutes = minutes; } period.prototype.format =()=> {console.log(this === window); // => true this.hours + 'hours and' + this.minutes + 'minutes'; }; var walkperiod = new Period(2、30); walkperiod.format(); // =>「未定義の時間と未定義の数分」参照してください
「これ」の4つの香り
JavaScriptの「この」キーワードの穏やかな説明
JavaScriptこの謎(翻訳)
それを理解していない学生を強くお勧めします。上記の3つの記事をご覧ください。3つ目は2番目の記事の翻訳です。これについてご質問がある場合は、一緒に話し合い、コミュニケーションをとり、思考を促進し、一緒に進歩を遂げることができます。