私は、this
キーワードが何であるか、そしてStack OverflowサイトのJavaScriptでそれがどのように正しく(そして間違って)使用されているかの明確な説明がないように思われることに気づきました。
私はそれでいくつかの非常に奇妙なふるまいを目撃しました、そして、なぜそれが起こったのか理解できませんでした。
this
はどのように機能し、いつ使うべきですか?
最初に Mike West の記事 JavaScriptのスコープ ( mirror )を読むことをお勧めします。これは、JavaScriptのthis
およびスコープチェーンの概念の優れたわかりやすい紹介です。
this
に慣れ始めたら、ルールは実際には非常に簡単です。 ECMAScript 5.1 Standard はthis
を定義します:
§11.1.1
this
キーワード
this
キーワードは、現在の実行コンテキストのThisBindingの値に評価されます
ThisBindingは、オブジェクトへの参照を保持する特別なCPUレジスタのように、JavaScriptインタープリターがJavaScriptコードを評価するときに保持するものです。インタプリタは、次の3つの異なるケースのいずれかで実行コンテキストを確立するたびにThisBindingを更新します。
これは、トップレベルで評価されるJavaScriptコードの場合です。 <script>
内に直接ある場合:
<script>
alert("I'm evaluated in the initial global execution context!");
setTimeout(function () {
alert("I'm NOT evaluated in the initial global execution context.");
}, 1);
</script>
初期グローバル実行コンテキストでコードを評価する場合、ThisBindingはグローバルオブジェクトwindow
( §10.4.1.1 )に設定されます。
…eval()
への直接呼び出しによるThisBindingは変更されません。呼び出し実行コンテキストのThisBindingと同じ値です( §10.4.2 (2)(a))。
…eval()
を直接呼び出していない場合
ThisBindingはグローバルオブジェクトに設定されますas if初期のグローバル実行コンテキストで実行中( §10.4.2 (1))。
§15.1.2.1.1は、eval()
の直接呼び出しが何であるかを定義します。基本的に、eval(...)
は直接呼び出しですが、(0, eval)(...)
やvar indirectEval = eval; indirectEval(...);
などはeval()
の間接呼び出しです。 JavaScriptで chuckjの答え to (1、eval)( 'this')vs eval( 'this')を参照してください。 および Dmitry SoshnikovのECMA-262-5の詳細。第2章厳密モード。 間接的なeval()
呼び出しを使用する場合。
これは、関数を呼び出すときに発生します。 obj.myMethod()
または同等のobj["myMethod"]()
などのオブジェクトで関数が呼び出された場合、ThisBindingはオブジェクトに設定されます(例ではobj
; §13.2.1 )。他のほとんどの場合、ThisBindingはグローバルオブジェクトに設定されます( §10.4.3 )。
「他のほとんどの場合」と書く理由は、引数リストでThisBindingを指定できるECMAScript 5組み込み関数が8つあるためです。これらの特殊関数は、いわゆるthisArg
を取ります。これは、関数を呼び出すときにThisBindingになります( §10.4.3 )。
これらの特別な組み込み関数は次のとおりです。
Function.prototype.apply( thisArg, argArray )
Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
Array.prototype.every( callbackfn [ , thisArg ] )
Array.prototype.some( callbackfn [ , thisArg ] )
Array.prototype.forEach( callbackfn [ , thisArg ] )
Array.prototype.map( callbackfn [ , thisArg ] )
Array.prototype.filter( callbackfn [ , thisArg ] )
Function.prototype
関数の場合、関数オブジェクトで呼び出されますが、ThisBindingを関数オブジェクトに設定するのではなく、ThisBindingをthisArg
に設定します。
Array.prototype
関数の場合、指定されたcallbackfn
は、ThisBindingがthisArg
に設定されている場合に設定される実行コンテキストで呼び出されます。それ以外の場合は、グローバルオブジェクトに。
これらはプレーンJavaScriptのルールです。 JavaScriptライブラリ(jQueryなど)の使用を開始すると、特定のライブラリ関数がthis
の値を操作することがあります。 JavaScriptライブラリの開発者は、最も一般的なユースケースをサポートする傾向があるため、これを行います。通常、ライブラリのユーザーは、この動作がより便利であると感じています。 this
を参照するコールバック関数をライブラリ関数に渡す場合、関数が呼び出されたときにthis
の値が何であるかについての保証については、ドキュメントを参照する必要があります。
JavaScriptライブラリがthis
の値をどのように操作するのか疑問に思っている場合、ライブラリはthisArg
を受け入れる組み込みJavaScript関数の1つを単に使用しています。あなたも、コールバック関数とthisArg
を使用して独自の関数を作成できます。
function doWork(callbackfn, thisArg) {
//...
if (callbackfn != null) callbackfn.call(thisArg);
}
まだ言及していない特別なケースがあります。 new
演算子を使用して新しいオブジェクトを作成する場合、JavaScriptインタープリターは新しい空のオブジェクトを作成し、いくつかの内部プロパティを設定してから、新しいオブジェクトでコンストラクター関数を呼び出します。したがって、コンストラクターコンテキストで関数が呼び出されると、this
の値はインタープリターが作成した新しいオブジェクトになります。
function MyType() {
this.someData = "a string";
}
var instance = new MyType();
// Kind of like the following, but there are more steps involved:
// var instance = {};
// MyType.call(instance);
矢印関数 (ECMA6で導入)this
のスコープを変更します。既存の標準的な質問、 矢印関数と関数宣言/式を参照してください:それらは同等/交換可能ですか? 詳細については。しかし、要するに:
矢印関数には、独自の
this
....バインディングがありません。代わりに、これらの識別子は他の変数と同様に字句スコープで解決されます。つまり、矢印関数内では、this
......矢印関数が定義されている環境のthis
の値を参照します。
回答を表示するには、明るい黄色のボックスの上にマウスを置きます。
マークされた行のthis
の値は何ですか?どうして?
window
—マークされた行は、初期グローバル実行コンテキストで評価されます。
if (true) {
// What is `this` here?
}
obj.staticFunction()
が実行されるとき、マークされた行のthis
の値は何ですか?どうして?
obj
—オブジェクトの関数を呼び出すと、ThisBindingがオブジェクトに設定されます。
var obj = {
someData: "a string"
};
function myFun() {
return this // What is `this` here?
}
obj.staticFunction = myFun;
console.log("this is window:", obj.staticFunction() == window);
console.log("this is obj:", obj.staticFunction() == obj);
マークされた行のthis
の値は何ですか?どうして?
window
この例では、JavaScriptインタープリターが関数コードを入力しますが、
myFun
/obj.myMethod
がオブジェクトで呼び出されないため、ThisBindingはwindow
に設定されます。これは、メソッド(
obj.myMethod
)にアクセスすると バインドメソッドオブジェクト が作成されるPythonとは異なります。
var obj = {
myMethod: function () {
return this; // What is `this` here?
}
};
var myFun = obj.myMethod;
console.log("this is window:", myFun() == window);
console.log("this is obj:", myFun() == obj);
マークされた行のthis
の値は何ですか?どうして?
window
これはトリッキーでした。評価コードを評価するとき、
this
はobj
です。ただし、評価コードでは、オブジェクトでmyFun
が呼び出されないため、呼び出しに対してThisBindingがwindow
に設定されます。
function myFun() {
return this; // What is `this` here?
}
var obj = {
myMethod: function () {
eval("myFun()");
}
};
マークされた行のthis
の値は何ですか?どうして?
obj
行
myFun.call(obj);
は、thisArg
を最初の引数として受け入れる特別な組み込み関数Function.prototype.call()
を呼び出しています。
function myFun() {
return this; // What is `this` here?
}
var obj = {
someData: "a string"
};
console.log("this is window:", myFun.call(obj) == window);
console.log("this is obj:", myFun.call(obj) == obj);
this
キーワードは、JavaScriptでは他の言語とは動作が異なります。オブジェクト指向言語では、this
キーワードはクラスの現在のインスタンスを参照します。 JavaScriptでは、this
の値は主にfunction(context.function()
)の呼び出しコンテキストとそれが呼び出される場所によって決定されます。
1.グローバルな場合
this
をグローバルコンテキストで使用すると、グローバルオブジェクトにバインドされます(ブラウザのwindow
)
document.write(this); //[object Window]
グローバルコンテキストで定義された関数内でthis
を使用すると、その関数は実際にはグローバルコンテキストのメソッドになるため、this
は依然としてグローバルオブジェクトにバインドされます。
function f1()
{
return this;
}
document.write(f1()); //[object Window]
上記のf1
はグローバルオブジェクトのメソッドになります。したがって、window
オブジェクトで次のように呼び出すこともできます。
function f()
{
return this;
}
document.write(window.f()); //[object Window]
2.オブジェクトメソッド内で使用した場合
オブジェクトメソッド内でthis
キーワードを使用すると、this
は「直接」を囲むオブジェクトにバインドされます。
var obj = {
name: "obj",
f: function () {
return this + ":" + this.name;
}
};
document.write(obj.f()); //[object Object]:obj
上記の言葉を二重引用符で囲みます。オブジェクトを別のオブジェクトの内側にネストすると、this
は直接の親にバインドされるということになります。
var obj = {
name: "obj1",
nestedobj: {
name:"nestedobj",
f: function () {
return this + ":" + this.name;
}
}
}
document.write(obj.nestedobj.f()); //[object Object]:nestedobj
メソッドとしてオブジェクトに関数を明示的に追加しても、それはまだ上記の規則に従います。つまり、this
はまだ直接の親オブジェクトを指しています。
var obj1 = {
name: "obj1",
}
function returnName() {
return this + ":" + this.name;
}
obj1.f = returnName; //add method to object
document.write(obj1.f()); //[object Object]:obj1
3.コンテキストレス機能を呼び出す場合
コンテキストなしで(つまり、どのオブジェクトに対しても)呼び出されない関数内でthis
を使用すると、グローバル関数(ブラウザ内ではwindow
)にバインドされます(関数がオブジェクト内で定義されている場合でも)。
var context = "global";
var obj = {
context: "object",
method: function () {
function f() {
var context = "function";
return this + ":" +this.context;
};
return f(); //invoked without context
}
};
document.write(obj.method()); //[object Window]:global
機能で全部試して
上記の点も関数で試すことができます。ただし、いくつか違いがあります。
this
を使って関数にメンバーを追加することができます。それらを指定します。new
演算子を使ってインスタンスを作成する必要があります。以下では、Objectとthis
を使って行ったことをすべて試しましたが、直接オブジェクトを書くのではなく、まず関数を作成しました。
/*********************************************************************
1. When you add variable to the function using this keyword, it
gets added to the function prototype, thus allowing all function
instances to have their own copy of the variables added.
*********************************************************************/
function functionDef()
{
this.name = "ObjDefinition";
this.getName = function(){
return this+":"+this.name;
}
}
obj1 = new functionDef();
document.write(obj1.getName() + "<br />"); //[object Object]:ObjDefinition
/*********************************************************************
2. Members explicitly added to the function protorype also behave
as above: all function instances have their own copy of the
variable added.
*********************************************************************/
functionDef.prototype.version = 1;
functionDef.prototype.getVersion = function(){
return "v"+this.version; //see how this.version refers to the
//version variable added through
//prototype
}
document.write(obj1.getVersion() + "<br />"); //v1
/*********************************************************************
3. Illustrating that the function variables added by both above
ways have their own copies across function instances
*********************************************************************/
functionDef.prototype.incrementVersion = function(){
this.version = this.version + 1;
}
var obj2 = new functionDef();
document.write(obj2.getVersion() + "<br />"); //v1
obj2.incrementVersion(); //incrementing version in obj2
//does not affect obj1 version
document.write(obj2.getVersion() + "<br />"); //v2
document.write(obj1.getVersion() + "<br />"); //v1
/*********************************************************************
4. `this` keyword refers to the immediate parent object. If you
nest the object through function prototype, then `this` inside
object refers to the nested object not the function instance
*********************************************************************/
functionDef.prototype.nestedObj = { name: 'nestedObj',
getName1 : function(){
return this+":"+this.name;
}
};
document.write(obj2.nestedObj.getName1() + "<br />"); //[object Object]:nestedObj
/*********************************************************************
5. If the method is on an object's prototype chain, `this` refers
to the object the method was called on, as if the method was on
the object.
*********************************************************************/
var ProtoObj = { fun: function () { return this.a } };
var obj3 = Object.create(ProtoObj); //creating an object setting ProtoObj
//as its prototype
obj3.a = 999; //adding instance member to obj3
document.write(obj3.fun()+"<br />");//999
//calling obj3.fun() makes
//ProtoObj.fun() to access obj3.a as
//if fun() is defined on obj3
4.コンストラクタ関数内で使用する場合 .
関数がコンストラクターとして使用されている場合(つまり、new
キーワードを指定して呼び出されている場合)、関数本体内のthis
は、作成中の新しいオブジェクトを指します。
var myname = "global context";
function SimpleFun()
{
this.myname = "simple function";
}
var obj1 = new SimpleFun(); //adds myname to obj1
//1. `new` causes `this` inside the SimpleFun() to point to the
// object being constructed thus adding any member
// created inside SimipleFun() using this.membername to the
// object being constructed
//2. And by default `new` makes function to return newly
// constructed object if no explicit return value is specified
document.write(obj1.myname); //simple function
5.プロトタイプチェーンで定義した関数内で使用した場合
メソッドがオブジェクトのプロトタイプチェーン上にある場合、そのメソッド内のthis
は、そのメソッドがオブジェクト上で定義されているかのように、そのメソッドが呼び出されたオブジェクトを参照します。
var ProtoObj = {
fun: function () {
return this.a;
}
};
//Object.create() creates object with ProtoObj as its
//prototype and assigns it to obj3, thus making fun()
//to be the method on its prototype chain
var obj3 = Object.create(ProtoObj);
obj3.a = 999;
document.write(obj3.fun()); //999
//Notice that fun() is defined on obj3's prototype but
//`this.a` inside fun() retrieves obj3.a
6.内部のcall()、apply()、bind()関数
Function.prototype
で定義されています。this
の値を指定することができます。それらはまた、呼び出されたときに元の関数に渡されるパラメータも取ります。fun.apply(obj1 [, argsArray])
fun()
内のthis
の値としてobj1
を設定し、その引数としてargsArray
の要素を渡してfun()
を呼び出します。fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- fun()
内のthis
の値としてobj1
を設定し、その引数としてarg1, arg2, arg3, ...
を渡してfun()
を呼び出します。fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- fun内のfun
をobj1
にバインドし、this
のパラメーターをarg1, arg2, arg3,...
で指定したパラメーターにバインドした関数fun
への参照を返します。apply
、call
、およびbind
の違いが明らかになっているはずです。 apply
は、配列のようなオブジェクト、すなわち数値のlength
プロパティおよび対応する負でない整数プロパティを持つオブジェクトとして機能するための引数を指定することを可能にします。 call
では、関数への引数を直接指定できます。 apply
とcall
は両方とも、指定されたコンテキストで指定された引数を使用して関数を直ちに呼び出します。一方、bind
は、指定されたthis
値と引数にバインドされた関数を単に返します。この返された関数への参照を変数に代入することで取得でき、後でいつでも呼び出すことができます。function add(inc1, inc2)
{
return this.a + inc1 + inc2;
}
var o = { a : 4 };
document.write(add.call(o, 5, 6)+"<br />"); //15
//above add.call(o,5,6) sets `this` inside
//add() to `o` and calls add() resulting:
// this.a + inc1 + inc2 =
// `o.a` i.e. 4 + 5 + 6 = 15
document.write(add.apply(o, [5, 6]) + "<br />"); //15
// `o.a` i.e. 4 + 5 + 6 = 15
var g = add.bind(o, 5, 6); //g: `o.a` i.e. 4 + 5 + 6
document.write(g()+"<br />"); //15
var h = add.bind(o, 5); //h: `o.a` i.e. 4 + 5 + ?
document.write(h(6) + "<br />"); //15
// 4 + 5 + 6 = 15
document.write(h() + "<br />"); //NaN
//no parameter is passed to h()
//thus inc2 inside add() is `undefined`
//4 + 5 + undefined = NaN</code>
7.イベントハンドラ内のthis
this
を使用すると、対応する要素が参照されます。そのような直接の関数割り当てはaddeventListener
メソッドを使うか、onclick
のような伝統的なイベント登録メソッドを通して行うことができます。<button onclick="...this..." >
など)のすぐ内側でthis
を使用すると、それは要素を参照します。this
を使用すると、グローバルオブジェクトwindow
に解決されます。attachEvent
を使用して、関数をイベントハンドラにアタッチすると、上記と同じ動作が実現されます。関数をイベントハンドラに割り当てる(そして要素の関数メソッドを作成する)代わりに、イベントで関数を呼び出します(実質的にグローバルコンテキストで呼び出します)。私は JSFiddle でこれを試してみることをお勧めします
<script>
function clickedMe() {
alert(this + " : " + this.tagName + " : " + this.id);
}
document.getElementById("button1").addEventListener("click", clickedMe, false);
document.getElementById("button2").onclick = clickedMe;
document.getElementById("button5").attachEvent('onclick', clickedMe);
</script>
<h3>Using `this` "directly" inside event handler or event property</h3>
<button id="button1">click() "assigned" using addEventListner() </button><br />
<button id="button2">click() "assigned" using click() </button><br />
<button id="button3" onclick="alert(this+ ' : ' + this.tagName + ' : ' + this.id);">used `this` directly in click event property</button>
<h3>Using `this` "indirectly" inside event handler or event property</h3>
<button onclick="alert((function(){return this + ' : ' + this.tagName + ' : ' + this.id;})());">`this` used indirectly, inside function <br /> defined & called inside event property</button><br />
<button id="button4" onclick="clickedMe()">`this` used indirectly, inside function <br /> called inside event property</button> <br />
IE only: <button id="button5">click() "attached" using attachEvent() </button>
this
次の関数を考えてください。
function foo() {
console.log("bar");
console.log(this);
}
foo(); // calling the function
これは通常モードで実行していることに注意してください。つまり、厳密モードは使用されていません。
ブラウザで実行している場合、this
の値はwindow
として記録されます。これは、window
がWebブラウザのスコープ内のグローバル変数であるためです。
Node.jsのような環境でこれと同じコードを実行すると、this
はアプリケーションのグローバル変数を参照します。
厳密なモードでステートメント"use strict";
を関数宣言の先頭に追加してこれを実行すると、this
はどちらの環境でもグローバル変数を参照しなくなります。これは、厳密モードでの混乱を避けるために行われています。 this
は、この場合は単にundefined
をログに記録するだけです。これは定義ではないためです。
次のような場合、this
の値を操作する方法がわかります。
これを行うにはさまざまな方法があります。 forEach
やslice
のようにJavascriptでネイティブメソッドを呼び出した場合は、その場合のthis
変数がその関数を呼び出したObject
を参照していることをすでに知っているはずです(javascriptでは、Object
を含め、ほぼすべてArray
です) Function
s)例えば以下のコードを取ります。
var myObj = {key: "Obj"};
myObj.logThis = function () {
// I am a method
console.log(this);
}
myObj.logThis(); // myObj is logged
Object
がFunction
を保持するプロパティを含む場合、そのプロパティはメソッドと呼ばれます。このメソッドは、呼び出されると、常にthis
変数が関連付けられているObject
変数に設定されます。これは、厳密モードと非厳密モードの両方に当てはまります。
メソッドが別の変数に格納されている(またはコピーされている)場合、this
への参照は新しい変数には保存されなくなります。例えば:
// continuing with the previous code snippet
var myVar = myObj.thisMethod;
myVar();
// logs either of window/global/undefined based on mode of operation
より一般的な実用的なシナリオを考えます。
var el = document.getElementById('idOfEl');
el.addEventListener('click', function() { console.log(this) });
// the function called by addEventListener contains this as the reference to the element
// so clicking on our element would log that element itself
new
キーワードJavascriptのコンストラクタ関数を考えます。
function Person (name) {
this.name = name;
this.sayHello = function () {
console.log ("Hello", this);
}
}
var awal = new Person("Awal");
awal.sayHello();
// In `awal.sayHello`, `this` contains the reference to the variable `awal`
これはどのように作動しますか?それでは、new
キーワードを使用したときに何が起こるかを見てみましょう。
new
キーワードを使用して関数を呼び出すと、すぐにObject
型のPerson
が初期化されます。Object
のコンストラクタは、そのコンストラクタがPerson
に設定されています。また、typeof awal
はObject
のみを返すことにも注意してください。Object
にはPerson.prototype
のプロトタイプが割り当てられます。これは、Person
プロトタイプ内のすべてのメソッドまたはプロパティが、Person
を含むawal
のすべてのインスタンスで使用できることを意味します。Person
自体が呼び出されました。 this
は、新しく構築されたオブジェクトawal
への参照です。かなり簡単ですね。
公式のECMAScript仕様では、この種の関数は実際のconstructor
関数であるとは何も述べていないことに注意してください。それらは通常の関数であり、new
はどの関数にも使用できます。それは私達がそれらをそのように使用するということだけです、そしてそれ故私達はそれらをそのようなものとしてのみ呼びます。
call
とapply
そうです、function
もObjects
(そしてJavascriptの実際にはファーストクラスの変数)でもあるので、関数でさえも...それ自体が関数であるメソッドを持っています。
すべての関数はグローバルFunction
を継承しており、その多くのメソッドのうちの2つはcall
とapply
であり、両方ともそれらが呼び出される関数でthis
の値を操作するために使用できます。
function foo () { console.log (this, arguments); }
var thisArg = {myObj: "is cool"};
foo.call(thisArg, 1, 2, 3);
これはcall
の典型的な使用例です。基本的に最初のパラメータを取り、関数this
のfoo
をthisArg
への参照として設定します。 call
に渡される他のすべてのパラメータは、引数として関数foo
に渡されます。
そのため、上記のコードはコンソールに{myObj: "is cool"}, [1, 2, 3]
を記録します。どの関数でもthis
の値を変更するための非常に良い方法です。
apply
はcall
とほとんど同じですが、thisArg
と、関数に渡される引数を含む配列の2つのパラメータのみを取ります。したがって、上記のcall
呼び出しは、次のようにapply
に変換できます。
foo.apply(thisArg, [1,2,3])
call
とapply
は、2番目の箇条書きで説明したドットメソッド呼び出しによって設定されたthis
の値をオーバーライドすることができます。とても簡単:)
bind
!bind
はcall
とapply
の兄弟です。 JavascriptのグローバルFunction
コンストラクタからすべての関数に継承されるメソッドでもあります。 bind
とcall
/apply
の違いは、call
とapply
の両方が実際に関数を呼び出すということです。一方、bind
は、thisArg
とarguments
が事前設定された新しい関数を返します。これをよりよく理解するために例を見てみましょう。
function foo (a, b) {
console.log (this, arguments);
}
var thisArg = {myObj: "even more cool now"};
var bound = foo.bind(thisArg, 1, 2);
console.log (typeof bound); // logs `function`
console.log (bound);
/* logs `function () { native code }` */
bound(); // calling the function returned by `.bind`
// logs `{myObj: "even more cool now"}, [1, 2]`
3つの違いは?微妙ですが、使い方は異なります。 call
やapply
と同様に、bind
もドットメソッド呼び出しによって設定されたthis
の値を上書きします。
また、これら3つの関数はどちらも元の関数に変更を加えることはありません。 call
とapply
は、新たに構築された関数から値を返しますが、bind
は、新たに構築された関数自体を返します。
時々、あなたはthis
がスコープ、特にネストされたスコープによって変わるという事実を好まない。次の例を見てください。
var myObj = {
hello: function () {
return "world"
},
myMethod: function () {
// copy this, variable names are case-sensitive
var that = this;
// callbacks ftw \o/
foo.bar("args", function () {
// I want to call `hello` here
this.hello(); // error
// but `this` references to `foo` damn!
// oh wait we have a backup \o/
that.hello(); // "world"
});
}
};
上記のコードでは、this
の値はネストされたスコープによって変化していますが、元のスコープからthis
の値が必要でした。そのため、this
をthat
に「コピー」し、this
の代わりにそのコピーを使用しました。賢いでしょ?
索引:
this
には何が保持されていますか?new
キーワードを使用するとどうなりますか?this
とcall
を使ってapply
をどのように操作するのでしょうか。bind
を使う.this
のコピー.「これ」はすべて範囲に関するものです。すべての関数はそれ自身のスコープを持っています、そして、JSの中のすべてはオブジェクトなので、関数でさえも "this"を使ってそれ自身にいくつかの値を格納することができます。 OOP 101は "this"はオブジェクトの インスタンス にのみ適用可能であることを教えています。したがって、関数が実行されるたびに、その関数の新しい「インスタンス」は「this」という新しい意味を持ちます。
ほとんどの人は、次のような無名クロージャ関数の中で "this"を使おうとすると混乱します。
(関数(値){ this.value = value; $( '。some-elements')。each(関数(elt){ elt .innerHTML = this.value; //あー!!おそらく未定義 }); })(2);
だからここで、each()の中で、 "this"はあなたが期待する "value"を保持していません。
this.value = value;
(関数(値){ var self = this; //小さな変更 self.value = value; $( '。some-elements') .each(function(elt){ elt.innerHTML = self.value; // phew !! == 2 }); })(2);
やってみよう;あなたはプログラミングのこのパターンを好きになり始めるでしょう
このスレッドが盛り上がったので、私はthis
name__トピックに不慣れな読者のためにいくつかのポイントをまとめました。
this
name__の値はどのように決定されますか?私たちはこれを英語のような自然言語で代名詞を使うのと同じように使います。「ジョンはheが電車に乗ろうとしているので速く走っています。」Johnは電車に乗ろうとしています。
var person = {
firstName: "Penelope",
lastName: "Barrymore",
fullName: function () {
// We use "this" just as in the sentence above:
console.log(this.firstName + " " + this.lastName);
// We could have also written:
console.log(person.firstName + " " + person.lastName);
}
}
this
name__ は、オブジェクトが定義されている場所で関数が呼び出されるまで、値 が割り当てられません。グローバルスコープでは、すべてのグローバル変数と関数はwindow
name__オブジェクトで定義されています。したがって、グローバル関数内のthis
name__は、グローバルwindow
name__オブジェクトを参照します(そしてその値を持ちます)。
グローバル、およびどのオブジェクトにもバインドされていない無名関数内のuse strict
、this
name__が、値undefined
name__を保持している場合。
this
name__キーワードは 最も誤解される when:1)this
name__を使用するメソッドを借用します。2)this
name__を使用するメソッドを変数に割り当てます。3)this
name__を使用する関数はコールバック関数として渡されます。 4)this
name__はクロージャー(内部関数)の中で使われています。 (2)
ECMA Script 6 で定義されている場合、arrow-functionsは囲んでいる(関数またはグローバル)スコープからthis
name__バインディングを採用します。
function foo() {
// return an arrow function
return (a) => {
// `this` here is lexically inherited from `foo()`
console.log(this.a);
};
}
var obj1 = { a: 2 };
var obj2 = { a: 3 };
var bar = foo.call(obj1);
bar.call( obj2 ); // 2, not 3!
Arrow-functionsはbind()
を使用する代わりになりますが、それらが本質的に伝統的なthis
name__メカニズムを無効にしているということは重要です。 (1)
参考文献
Javascriptのthis
は常に 実行されている関数の '所有者' を参照します。
明示的な所有者が定義されていない場合は、最上位の所有者であるウィンドウオブジェクトが参照されます。
だから私がした場合
function someKindOfFunction() {
this.style = 'foo';
}
element.onclick = someKindOfFunction;
this
は要素オブジェクトを参照します。しかし、注意してください、多くの人がこの間違いを犯します
<element onclick="someKindOfFunction()">
後者の場合、あなたは単に関数を参照するだけで、それを要素に渡すことはしません。そのため、this
はウィンドウオブジェクトを参照します。
すべての 関数 実行コンテキスト javascriptでは/が 範囲コンテキスト this :によって設定されるパラメータ
そのスコープコンテキストが何であれ、 "this"によって参照されます。
あなたはできる それを変える this の値を設定 範囲コンテキスト func.call
、func.apply
またはfunc.bind
を使用します。
デフォルトでは、ほとんどの初心者を混乱させます。 callback DOM要素でイベントが発生した後にリスナーが呼び出されます。 スコープコンテキスト これ 関数の値はDOM要素です。
jQueryはjQuery.proxyでこれを簡単に変更します。
ここで はthis
の中のJavaScript
の良い情報源です。
概要は次のとおりです。
global this
ブラウザでは、グローバルスコープでthis
がwindow
オブジェクトです。
<script type="text/javascript">
console.log(this === window); // true
var foo = "bar";
console.log(this.foo); // "bar"
console.log(window.foo); // "bar"
Replを使用しているnode
では、this
が最上位のネームスペースです。あなたはそれをglobal
と呼ぶことができます。
>this
{ ArrayBuffer: [Function: ArrayBuffer],
Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 },
Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 },
...
>global === this
true
スクリプトから実行しているnode
では、グローバルスコープのthis
は空のオブジェクトとして始まります。 global
と同じではありません
\\test.js
console.log(this); \\ {}
console.log(this === global); \\ fasle
function this
DOMイベントハンドラの場合、またはthisArg
が呼び出されていない関数内でthis
を使用しているノード内およびブラウザ内の両方でnew
が提供されている場合を除いて、グローバルスコープを参照します。
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis();
console.log(this.foo); //logs "foo"
</script>
use strict;
を使用する場合、その場合this
はundefined
になります。
<script type="text/javascript">
foo = "bar";
function testThis() {
"use strict";
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
testThis(); //Uncaught TypeError: Cannot set property 'foo' of undefined
</script>
new
を使用して関数を呼び出すと、this
は新しいコンテキストになり、グローバルなthis
を参照しなくなります。
<script type="text/javascript">
foo = "bar";
function testThis() {
this.foo = "foo";
}
console.log(this.foo); //logs "bar"
new testThis();
console.log(this.foo); //logs "bar"
console.log(new testThis().foo); //logs "foo"
</script>
作成した関数は関数オブジェクトになります。それらは自動的に特別なprototype
プロパティを取得します。これはあなたが値を割り当てることができるものです。 new
を使用して関数を呼び出してインスタンスを作成すると、prototype
プロパティに割り当てた値にアクセスできます。これらの値にアクセスするにはthis
を使用します。
function Thing() {
console.log(this.foo);
}
Thing.prototype.foo = "bar";
var thing = new Thing(); //logs "bar"
console.log(thing.foo); //logs "bar"
通常、prototype
に配列またはオブジェクトを代入するのは誤りです。インスタンスごとに独自の配列が必要な場合は、プロトタイプではなく関数内にそれらを作成します。
function Thing() {
this.things = [];
}
var thing1 = new Thing();
var thing2 = new Thing();
thing1.things.Push("foo");
console.log(thing1.things); //logs ["foo"]
console.log(thing2.things); //logs []
オブジェクトの他のプロパティを参照するために、オブジェクトの任意の関数でthis
を使用できます。これはnew
で作成されたインスタンスと同じではありません。
var obj = {
foo: "bar",
logFoo: function () {
console.log(this.foo);
}
};
obj.logFoo(); //logs "bar"
HTML DOMイベントハンドラでは、this
は常にイベントが関連付けられたDOM要素への参照です。
function Listener() {
document.getElementById("foo").addEventListener("click",
this.handleClick);
}
Listener.prototype.handleClick = function (event) {
console.log(this); //logs "<div id="foo"></div>"
}
var listener = new Listener();
document.getElementById("foo").click();
コンテキストをbind
にしない限り
function Listener() {
document.getElementById("foo").addEventListener("click",
this.handleClick.bind(this));
}
Listener.prototype.handleClick = function (event) {
console.log(this); //logs Listener {handleClick: function}
}
var listener = new Listener();
document.getElementById("foo").click();
JavaScriptを入れることができるHTML属性の中で、this
は要素への参照です。
<div id="foo" onclick="console.log(this);"></div>
<script type="text/javascript">
document.getElementById("foo").click(); //logs <div id="foo"...
</script>
eval
を使用してthis
にアクセスできます。
function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
eval("console.log(this.foo)"); //logs "bar"
}
var thing = new Thing();
thing.logFoo();
with
を明示的に参照せずにthis
を現在のスコープに追加してthis
の値を読み書きするには、this
を使用します。
function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
with (this) {
console.log(foo);
foo = "foo";
}
}
var thing = new Thing();
thing.logFoo(); // logs "bar"
console.log(thing.foo); // logs "foo"
jQueryは多くの場所でthis
がDOM要素を参照するようにします。
<div class="foo bar1"></div>
<div class="foo bar2"></div>
<script type="text/javascript">
$(".foo").each(function () {
console.log(this); //logs <div class="foo...
});
$(".foo").on("click", function () {
console.log(this); //logs <div class="foo...
});
$(".foo").each(function () {
this.click();
});
</script>
おそらくthis
に関する最も詳細で包括的な記事は次のとおりです。
this
の背後にある考え方は、関数呼び出しタイプがthis
値の設定において非常に重要であることを理解することです。
this
を識別するのに問題があるときは、 しないでください 自分自身に尋ねてください。
this
from fromはどこにありますか?
しかし do 自分自身に尋ねる:
関数invokeはどうですか?
矢印機能(文脈透過の特別な場合)については、あなた自身に尋ねてください。
矢印関数がdefinedの場合、
this
はどのような値になりますか?
この考え方はthis
を扱うときに正しいので、頭痛からあなたを救うでしょう。
ダニエル、素晴らしい説明です。イベントハンドラの場合の、これとthis
実行コンテキストポインタの適切なリストに関するいくつかの単語。
つまり、JavaScriptのthis
は、現在の関数が実行された人(またはその実行コンテキスト)からのオブジェクトを指しており、常に読み取り専用です。それを設定することはできません。課題メッセージの手元.
イベントハンドラの場合: <element onclick="foo">
などのインラインイベントハンドラは、以前および以前にアタッチされている他のハンドラをオーバーライドするので、注意してください。インラインイベントの委任を避けるようにしてください。そして、異議を唱える議論を通してこの例のリストに私を奮い立たせたZara Alaverdyanに感謝します:)
el.onclick = foo; // in the foo - obj
el.onclick = function () {this.style.color = '#fff';} // obj
el.onclick = function() {doSomething();} // In the doSomething - Window
el.addEventListener('click',foo,false) // in the foo - obj
el.attachEvent('onclick, function () { // this }') // window, all the compliance to IE :)
<button onclick="this.style.color = '#fff';"> // obj
<button onclick="foo"> // In the foo - window, but you can <button onclick="foo(this)">
これは私が見た中で最高の説明です。 JavaScriptを理解する this Clarity付き
this referenceは、オブジェクト(単数オブジェクト)を常に参照(およびその値を保持)し、グローバルスコープ内の関数の外部で使用することもできます。 。厳密モードを使用する場合、これはグローバル関数内およびオブジェクトにバインドされていない無名関数内のundefinedの値を保持します。
this が混乱を招く可能性がある4つの条件があります。
彼は、コード例、説明、そして私がとても役に立ちそうだと思ったコード修正を与えます。
十分に理解していないと、JSを十分に理解したり、その中に何か些細なことを書いたりすることは困難です。私はJSを始めるための最良の方法はDouglas Crockfordによるこれらのビデオ講義を最初に見ることだと思います - http://yuiblog.com/crockford/ 、これをカバーしていますそれが、JSに関する他のすべてのことです。
擬古典的用語では、多くの講義が 'this'キーワードを教える方法は、クラスまたはオブジェクトコンストラクターによってインスタンス化されたオブジェクトとしてです。新しいオブジェクトがクラスから構築されるたびに、内部で「this」オブジェクトのローカルインスタンスが作成されて返されると想像してください。私はそれがこのように教えられたのを覚えています:
function Car(make, model, year) {
var this = {}; // under the hood, so to speak
this.make = make;
this.model = model;
this.year = year;
return this; // under the hood
}
var mycar = new Car('Eagle', 'Talon TSi', 1993);
// ========= under the hood
var this = {};
this.make = 'Eagle';
this.model = 'Talon TSi';
this.year = 1993;
return this;
this
はJavaScriptの誤解されている概念の1つです。これは、場所によって動作が多少異なるためです。簡単に言うと、this
は、現在実行している関数の 「所有者」 を指します。
this
は、現在のオブジェクト(実行コンテキスト)を取得するのに役立ちます。現在の関数がどのオブジェクトで実行されているのか理解できれば、現在のthis
がどんなものであるかを容易に理解することができます。
var val = "window.val"
var obj = {
val: "obj.val",
innerMethod: function () {
var val = "obj.val.inner",
func = function () {
var self = this;
return self.val;
};
return func;
},
outerMethod: function(){
return this.val;
}
};
//This actually gets executed inside window object
console.log(obj.innerMethod()()); //returns window.val
//Breakdown in to 2 lines explains this in detail
var _inn = obj.innerMethod();
console.log(_inn()); //returns window.val
console.log(obj.outerMethod()); //returns obj.val
上記の同じ名前 'val'で3つの変数を作成します。一方はobjの内側に、もう一方はobjのinnerMethodの内側にあります。 JavaScriptは、ローカルからグローバルにスコープチェーンを上がることによって、特定のコンテキスト内の識別子を解決します。
this
を区別できる場所はほとんどありません
var status = 1;
var helper = {
status : 2,
getStatus: function () {
return this.status;
}
};
var theStatus1 = helper.getStatus(); //line1
console.log(theStatus1); //2
var theStatus2 = helper.getStatus;
console.log(theStatus2()); //1
Line1が実行されると、JavaScriptは関数呼び出しの実行コンテキスト(EC)を確立し、最後の "。"の前にくるものが参照する オブジェクトにthis
を設定します。 。最後の行で、a()
がwindow
というグローバルコンテキストで実行されたことがわかります。
this
は、作成中のオブジェクトを参照するために使用できます。
function Person(name){
this.personName = name;
this.sayHello = function(){
return "Hello " + this.personName;
}
}
var person1 = new Person('Scott');
console.log(person1.sayHello()); //Hello Scott
var person2 = new Person('Hugh');
var sayHelloP2 = person2.sayHello;
console.log(sayHelloP2()); //Hello undefined
New Person()
が実行されると、全く新しいオブジェクトが作成されます。 Person
が呼び出され、そのthis
がその新しいオブジェクトを参照するように設定されます。
function testFunc() {
this.name = "Name";
this.myCustomAttribute = "Custom Attribute";
return this;
}
var whatIsThis = testFunc();
console.log(whatIsThis); //window
var whatIsThis2 = new testFunc();
console.log(whatIsThis2); //testFunc() / object
console.log(window.myCustomAttribute); //Custom Attribute
new
キーワードを見逃した場合、whatIsThis
はそれが見つけることができる最もグローバルなコンテキストを参照します(window
)
イベントハンドラがインラインの場合、this
はグローバルオブジェクトを参照します。
<script type="application/javascript">
function click_handler() {
alert(this); // alerts the window object
}
</script>
<button id='thebutton' onclick='click_handler()'>Click me!</button>
JavaScriptを通してイベントハンドラを追加するとき、this
はイベントを生成したDOM要素を参照します。
.apply()
.call()
と.bind()
を使ってコンテキストを操作することもできます。var that = this
はどういう意味ですか「this」の値は、関数が実行される「コンテキスト」によって異なります。コンテキストは、任意のオブジェクトまたはグローバルオブジェクト、つまりウィンドウにすることができます。
そのため、「これ」の意味は伝統的なOOP言語とは異なります。そしてそれは問題を引き起こします:1.関数が他の変数(たぶん、コールバック)に渡されるとき。クロージャがクラスのメンバメソッドから呼び出されたとき。
どちらの場合も、これはwindowに設定されています。
これ 助けになりますか? (JavaScriptでの 'this'の最も混乱は、それが一般的にあなたのオブジェクトではなく現在の実行スコープにリンクされているという事実から来ています - それは正確には機能しないかもしれませんがいつも私のように感じます - 完全な説明については記事を参照してください)
this キーワードについてのちょっとした情報
コードを追加せずに、グローバルスコープでthis
キーワードをコンソールに記録しましょう。
console.log(this)
クライアント/ブラウザ this
キーワードはwindow
であるグローバルオブジェクトです。
console.log(this === window) // true
そして
Server/Node/Javascript runtime this
キーワードもmodule.exports
であるグローバルオブジェクトです。
console.log(this === module.exports) // true
console.log(this === exports) // true
exports
は単にmodule.exports
への参照です
私はthis
を他の答えとは違う見方をしています。
JavaScriptを見る1つの方法は、関数を呼び出す方法が1つしかないことを確認することです。1。それは
functionObject.call(objectForThis, arg0, arg1, arg2, ...);
objectForThis
には常にいくつかの値が提供されています。
他のものはすべてfunctionObject.call
の構文糖です
それで、他のすべてはfunctionObject.call
に変換される方法によって記述することができます。
関数を呼び出すだけの場合、this
はブラウザ内のウィンドウである "グローバルオブジェクト"です。
function foo() {
console.log(this);
}
foo(); // this is the window object
言い換えると、
foo();
に効果的に翻訳された
foo.call(window);
厳密モードを使用する場合、this
はundefined
になります。
'use strict';
function foo() {
console.log(this);
}
foo(); // this is the window object
つまり
言い換えると、
foo();
に効果的に翻訳された
foo.call(undefined);
JavaScriptには+
と-
そして*
のような演算子があります。 .
であるドット演算子もあります
.
演算子は、右側の関数と左側のオブジェクトと共に使用すると、事実上「functionにthis
としてオブジェクトを渡すことを意味します。
例
const bar = {
name: 'bar',
foo() {
console.log(this);
},
};
bar.foo(); // this is bar
言い換えれば、bar.foo()
はconst temp = bar.foo; temp.call(bar);
に変換されます。
関数の作成方法は関係ありません(ほとんどの場合...)。これらのすべてが同じ結果を生成します
const bar = {
name: 'bar',
fn1() { console.log(this); },
fn2: function() { console.log(this); },
fn3: otherFunction,
};
function otherFunction() { console.log(this) };
bar.fn1(); // this is bar
bar.fn2(); // this is bar
bar.fn3(); // this is bar
繰り返しますが、これらはすべて構文糖にすぎません。
{ const temp = bar.fn1; temp.call(bar); }
{ const temp = bar.fn2; temp.call(bar); }
{ const temp = bar.fn3; temp.call(bar); }
もう一つのしわはプロトタイプチェーンです。 a.b
を使用すると、JavaScriptはまずa
によって直接参照されているオブジェクトでプロパティb
を調べます。オブジェクトにb
が見つからない場合、JavaScriptはオブジェクトのプロトタイプを調べてb
を見つけます。
オブジェクトのプロトタイプを定義するにはさまざまな方法があります。2019で最も一般的なのはclass
キーワードです。 this
の目的では問題ありませんが。重要なのは、オブジェクトa
のプロパティb
がオブジェクトのproperty b
を見つけた場合、またはプロトタイプチェーンの中でb
が関数になった場合です。上記と同じ規則が適用されます。関数b
参照は、call
メソッドを使用し、object []としてa
を渡すことで呼び出されます。この回答の冒頭に示したとおりです。
今すぐ別の関数を呼び出す前にthis
を明示的に設定してから.
(dot)演算子で呼び出す関数を作成したとしましょう。
function foo() {
console.log(this);
}
function bar() {
const objectForThis = {name: 'moo'}
foo.call(objectForThis); // explicitly passing objectForThis
}
const obj = {
bar,
};
obj.bar();
call
を使用するように変換すると、obj.bar()
はconst temp = obj.bar; temp.call(obj);
になります。 bar
関数に入るときは、foo
を呼び出しますが、objectForThisに別のオブジェクトを明示的に渡したので、foo this
に到達したときはその内部オブジェクトです。
これがbind
関数と=>
関数の両方が効果的に行うことです。彼らはもっと統語的な砂糖です。指定された関数を呼び出す前に明示的にbar
を設定する上記のthis
とまったく同じように、見えない新しい関数を効果的に構築します。 bindの場合、this
はbind
に渡すものに設定されます。
function foo() {
console.log(this);
}
const bar = foo.bind({name: 'moo'});
// bind created a new invisible function that calls foo with the bound object.
bar();
// the objectForThis we are passing to bar here is ignored because
// the invisible function that bind created will call foo with with
// the object we bound above
bar.call({name: 'other'});
functionObject.bind
が存在しない場合は、次のように独自のものを作成できます。
function bind(fn, objectForThis) {
return function(...args) {
return fn.call(objectForthis, ...args);
};
}
そしてそれを次のように呼ぶことができます
function foo() {
console.log(this);
}
const bar = bind(foo, {name:'abc'});
矢印関数、=>
演算子はバインドのための構文糖です
const a = () => {console.log(this)};
と同じです
const tempFn = function() {console.log(this)};
const a = tempFn.bind(this);
bind
と同じように、objectForThis
のバインド値を使用して指定の関数を呼び出す新しい不可視関数が作成されますが、bind
とは異なり、バインドされるオブジェクトは暗黙的です。 =>
演算子が使用されたときにthis
が発生することは何でもです。
それで、ちょうど上の規則のように
const a = () => { console.log(this); } // this is the global object
'use strict';
const a = () => { console.log(this); } // this is undefined
function foo() {
return () => { console.log(this); }
}
const obj = {
foo,
};
const b = obj.foo();
b();
obj.foo()
はconst temp = obj.foo; temp.call(obj);
に変換されます。これは、foo
内の矢印演算子がobj
を新しい不可視関数にバインドし、b
に割り当てられた新しい不可視関数を返すことを意味します。 b()
は、foo
が作成した新しい不可視関数を呼び出すb.call(window)
またはb.call(undefined)
と同じように動作します。その見えない関数は、渡されたthis
を無視し、object関数としてobj
をarrow関数に渡します。
上記のコードは
function foo() {
function tempFn() {
console.log(this);
}
return tempFn.bind(this);
}
const obj = {
foo,
};
const b = obj.foo();
b.call(window or undefined if strict mode);
1apply
はcall
に似た別の関数です。
functionName.apply(objectForThis, arrayOfArgs);
しかしES6では、概念的にそれを以下のようにも翻訳できます。
functionName.call(objectForThis, ...arrayOfArgs);
このようにScopeに使用する
<script type="text/javascript" language="javascript">
$('#tbleName tbody tr').each(function{
var txt='';
txt += $(this).find("td").eq(0).text();
\\same as above but synatx different
var txt1='';
txt1+=$('#tbleName tbody tr').eq(0).text();
alert(txt1)
});
</script>
txt1とtxtの値は上の例と同じです$(this)= $( '#tbleName tbody tr')は同じです
this
Javascript:this
の値は、_関数の呼び出し方ではなく、作成場所によって決まります。this
の値はドットの左側にあるObjectによって決定されます。 (グローバル空間でwindow
)this
の値はイベントが呼び出されたDOM要素を参照します。new
キーワードを使用して呼び出されると、this
の値は新しく作成されたオブジェクトを参照しますthis
の値は、関数call
、apply
、bind
を使って操作できます。let object = {
prop1: function () {console.log(this);}
}
object.prop1(); // object is left of the dot, thus this is object
const myFunction = object.prop1 // We store the function in the variable myFunction
myFunction(); // Here we are in the global space
// myFunction is a property on the global object
// Therefore it logs the window object
document.querySelector('.foo').addEventListener('click', function () {
console.log(this); // This refers to the DOM element the eventListener was invoked from
})
document.querySelector('.foo').addEventListener('click', () => {
console.log(this); // Tip, es6 arrow function don't have their own binding to the this v
}) // Therefore this will log the global object
.foo:hover {
color: red;
cursor: pointer;
}
<div class="foo">click me</div>
function Person (name) {
this.name = name;
}
const me = new Person('Willem');
// When using the new keyword the this in the constructor function will refer to the newly created object
console.log(me.name);
// Therefore, the name property was placed on the object created with new keyword.
JavaScriptの「this」キーワードとは
このキーワードは、オブジェクト、つまりJavaScriptコードの現在のビットを実行しているオブジェクトを参照します。
言い換えれば、実行中のすべてのJavaScript関数は、thisという現在の実行コンテキストへの参照を持ちます。実行コンテキストとは、関数がどのように呼び出されるかを意味します。
このキーワードを理解するためには、関数が呼び出される場所、場所、場所、および宣言される方法や定義される場所が問題にならない方法を知っておく必要があります。
function bike() {
console.log(this.name);
}
var name = "Ninja";
var obj1 = { name: "Pulsar", bike: bike };
var obj2 = { name: "Gixxer", bike: bike };
bike(); // "Ninja"
obj1.bike(); // "Pulsar"
obj2.bike(); // "Gixxer"
上記のコードスニペットでは、bike()
関数の仕事はthis.name
を印刷することです。これは、現在の実行コンテキスト(i.e.this object)
のnameプロパティの値を印刷しようとしていることを意味します。
上記のコードスニペットでは、関数bike()
が呼び出されると、実行のコンテキストが指定されていないのでデフォルトでそのグローバルコンテキストがあり、グローバルコンテキストに値が "Ninja"の変数名が存在するため、 "Ninja"を出力します。
obj1().bike()
呼び出しの場合、「Pulsar」が出力され、その背後にある理由は関数bike()
が実行コンテキストをobj1
として呼び出すため、this.name
はobj1.name
になります。関数obj2.bike()
の実行コンテキストがobj2
であるbike()
呼び出しと同じです。
「this」のデフォルトおよび暗黙の束縛
厳密モードの場合、このキーワードのデフォルト値は未定義です。それ以外の場合、このキーワードはグローバルオブジェクトとして機能します。このキーワードのデフォルトバインディングと呼びます。 ( ブラウザの場合のデフォルトはウィンドウオブジェクト )。
私たちがメソッドとして呼んでいるオブジェクトプロパティがあるとき、そのオブジェクトはこのオブジェクトまたはそのメソッドの実行コンテキストオブジェクトになります、それはこのキーワードの暗黙の束縛です。
var obj1 = {
name: "Pulsar",
bike: function() {
console.log(this.name);
}
}
var obj2 = { name: "Gixxer", bike: obj1.bike };
var name = "Ninja";
var bike = obj1.bike;
bike(); // "Ninja"
obj1.bike(); // "Pulsar"
obj2.bike(); // "Gixxer"
上記のコードスニペットでは、関数呼び出しbike()
がデフォルトバインディングの例です。 obj1.bike()
およびobj2.bike()
は、暗黙的バインドの例です。ここではバイク関数はobj1
の一部として宣言されていますが、それに関係なく、executeobj2.bike()
の実行のコンテキストはobj2
なので、obj2.name
が出力されます。
関数がいつ、どこから呼び出されても、どこで関数が宣言されていても構わないということを知っておくことは重要です。
「this」キーワードの明示的および固定的なバインディング
Callとapplyメソッドを呼び出し関数と一緒に使用する場合、それらのメソッドは両方とも実行コンテキストとしての最初のパラメータとして使用されます。それがこの拘束力です。
function bike() {
console.log(this.name);
}
var name = "Ninja";
var obj = { name: "Pulsar" }
bike(); // "Ninja"
bike.call(obj); // "Pulsar"
このスニペットで、実行コンテキストオブジェクトobjを最初の引数として渡してcall()
メソッドで関数bikeを呼び出すと、objはこのオブジェクトに割り当てられ、obj.name
以外の何もない“ Pulsar”を出力します。このキーワードの明示的な結合と呼ばれています。
固定綴じまたはハード綴じ
どこでどのように呼び出されても、thisオブジェクトを常に同じにすることができます。
var bike = function() {
console.log(this.name);
}
var name = "Ninja";
var obj1 = { name: "Pulsar" };
var obj2 = { name: "Gixxer" };
var originalBikeFun = bike;
bike = function() {
originalBikeFun.call(obj1);
};
bike(); // "Pulsar"
bike.call(obj2); // "Pulsar"
上記のコードスニペットのとおり、bike()
とbike.call(obj2)
はどちらも "Pulsar"を呼び出します。これはobj1.name
以外の何ものでもなく、関数バイクの実行コンテキストは常にobj1
であり、その理由はoriginalBikeFun.call(obj1)
です。この種のこの束縛は、固定束縛と呼ばれるもう1つの明示的な束縛の一種です。