jsのthisキーワードの理解について
12162 ワード
このキーワードはc++,javaで提供されているので、勉強を始めたばかりの頃は難しいと思いましたが、理解すれば使いやすくなります.
これについては、フロントエンドの面接で必ず受けるテーマがたくさんあります.时にはネットでこれらのテーマを見て、自分でやってみました.ええ、本当に間違っています.実際の開発では、この問題にも遭遇します(一部のクラスライブラリでは処理されますが)、例えば、いくつかのフレームワークを使用する場合、例えば、knockout、なぜ直接thisを使用しないのか分からない場合がありますが、これをパラメータとして入力します.
次に私の理解について話して、メモとしても、後で参照するのに便利です.悪いところがあったら、批判を歓迎します.
1. C#とは異なり、これは現在のオブジェクトを指しているに違いありません.
jsのthis指向は不確定であり,すなわち動的に変化できる.call/applyはthisが指す関数を変更するために使用され、コードをより柔軟にし、多重性を高めることができます.
2. この場合、一般的には、関数の所有者を指します.
この点が重要です!この点が重要です!この点が重要です!
これもよくある面接問題で、次のコードがあります.
showNumberメソッドの所有者はobjであるため、this.number=3; これはobjのプロパティnumberを指します.
同じように2番目のconsole.log印刷もプロパティnumberです.
なぜ第二に、一般的にはthisは関数の所有者を指しているのか.特別な状況があるからだ.関数の自己実行は特殊な場合で、関数の自己実行の中で、thisはwindowを指します.だから最初のconsole.logはwindowのプロパティnumberを印刷します.
だから少し追加します.
3. 関数の自己実行では、thisはwindowオブジェクトを指します.
拡張、thisについて、domイベントでは、通常次の3つのケースがあります.
次のようになります.
1. ラベルプロパティを使用してイベントを登録します.この場合、thisはwindowオブジェクトを指します.
2. 1の場合、thisをinputに向けるには、thisをパラメータとして渡すことができます.
3. addEventListenerなどを使用して登録します.このときthisもinputを指します.
オブジェクト向けプログラミング言語では、thisキーワードについてよく知られています.例えばC++、C#、Javaなどがこのキーワードを提供しているので、勉強を始めるときは難しいと思いますが、理解さえすれば、とても便利で意味が確定します.JavaScriptもこのthisキーワードを提供していますが、古典的なOO言語よりも「混乱」しています.
次に、JavaScriptでのthisの使い方の乱れを見てみましょう.
1、HTML要素イベント属性においてinline方式でthisキーワードを使用する:
一般的によく使われる方法は、javascirpt:EventHandler(this)という形式です.しかし、ここでは合法的なJavaScript文を書くことができます.ここでクラスを定義してもいいです(ただし、内部クラスになります).ここでの原理は、スクリプトエンジンがdivインスタンスオブジェクトの匿名メンバーメソッドを生成し、onclickがこのメソッドを指すことである.
2、DOM方式でイベント処理関数にthisキーワードを使用する:
このときのEventHandler()メソッドのthisキーは,IEのwindowオブジェクトを示す.これはEventHandlerが一般的な関数にすぎず、attachEventの後、スクリプトエンジンはその呼び出しとdivオブジェクト自体に何の関係もないためです.また、nullに等しいEventHandlerのcallerプロパティも参照できます.この方法でdivオブジェクト参照を取得する場合は、thisを使用します.event.srcElement.
3、DHTML方式でイベント処理関数でthisキーワードを使用する:
ここでthisキーはdiv要素オブジェクトインスタンスを示し、スクリプトでDHTML方式を使用してdiv.onclickに直接EventHandlerを割り当てる方法であり、divオブジェクトインスタンスにメンバーメソッドを追加することに等しい.この方式と第1の方法の違いは、第1の方法はHTML方式を使用することであり、ここではDHTML方式であり、後者のスクリプト解析エンジンは匿名の方法を生成しない.
4、クラス定義でthisキーワードを使用する:
これはJavaScriptシミュレーションクラス定義におけるthisの使用であり,これは他のOO言語の場合と非常によく知られている.ただし、ここではメンバーのプロパティとメソッドをthisキーで参照する必要があります.上記のプログラムを実行するとmyNameが定義されていないことが通知されます.
5、スクリプトエンジンの内部オブジェクトに原形メソッドのthisキーワードを追加する:
ここでthisとは、原形が追加されたクラスの例を指し、4のクラス定義と少し似ていて、あまり特別なところはありません.
6、2&4を組み合わせて、迷っているthisキーワードを使います.
結果についてお話ししますと、ページが実行されると「division element」と表示され、確定したら「division element」という文字をクリックすると「undefined」と表示されます.
7、CSSのexpression式でthisキーワードを使用する:
ここでthisは1と同様にすればよいと考えられ、div要素オブジェクトインスタンス自体を指す.
8、関数の内部関数でthisキーを使用する:
実行結果は、「Inner Name,Outer Name」と表示されます.2の説明では、ここの結果が「Inner Name,undefined」ならもっと合理的なようですね?しかし、正確な結果は確かに前者であり、これはJavaScript変数の役割ドメインの問題によって決定されたものであり、「元のJscriptのキーワード「var」には文章があるのか」の一文と返事を詳しく理解することを推奨する.
まとめてみると、JavaScriptのthisの使い方は、以下の3つあります(詳しくは原文参照).
1.HTML要素イベント属性またはCSSのexpression式でinline方式でthisキーワードを使用――原文の1、7に対応
2.イベント処理関数にthisキーを使用――原文に対応する2,3
このうち2つの方法に分けることができます
(1)DOM方式――この方式の結果はthisがウィンドウオブジェクトを指す
(2)DHTML方式――この方式の結果、thisがdiv要素オブジェクトを指す例
3.クラス定義でthisキーワードを使用し、その内部関数またはメンバー関数(主にprototype生成)で使用します.原文の4、5、8に対応します.
なお、関数でもオブジェクトであるため、次のように変数定義とメンバー変数定義を区別する必要があります.
以上まとめた3種類のthisの使用方法のうち、1つ目は比較的理解しやすく、ここでは原文の6点に記載のプログラムをテストし、以下のように改善し、上記の2つの使用方法を説明した.
上記のコードの実行結果は、次のとおりです.
ページがロードされると、ダイアログボックスがポップアップされ、func memberが出力されます.
ページに表示
func variableをクリックすると、ポップアップダイアログボックスが開き、undefinedが表示されます.
――このときtoString関数のthisポインタがwindowを指しているため
new elementをクリックすると、ポップアップダイアログボックスにnew element textが表示されます.
――toString関数のthisポインタがdiv要素を指しているため、この要素はm_を定義しています.Textメンバー(this.newElement.m_Text="new element text!")
これについては、フロントエンドの面接で必ず受けるテーマがたくさんあります.时にはネットでこれらのテーマを見て、自分でやってみました.ええ、本当に間違っています.実際の開発では、この問題にも遭遇します(一部のクラスライブラリでは処理されますが)、例えば、いくつかのフレームワークを使用する場合、例えば、knockout、なぜ直接thisを使用しないのか分からない場合がありますが、これをパラメータとして入力します.
次に私の理解について話して、メモとしても、後で参照するのに便利です.悪いところがあったら、批判を歓迎します.
1. C#とは異なり、これは現在のオブジェクトを指しているに違いありません.
jsのthis指向は不確定であり,すなわち動的に変化できる.call/applyはthisが指す関数を変更するために使用され、コードをより柔軟にし、多重性を高めることができます.
2. この場合、一般的には、関数の所有者を指します.
この点が重要です!この点が重要です!この点が重要です!
これもよくある面接問題で、次のコードがあります.
var number = 1;
var obj = {
number: 2,
showNumber: function(){
this.number = 3;
(function(){
console.log(this.number);
})();
console.log(this.number);
}
};
obj.showNumber();
showNumberメソッドの所有者はobjであるため、this.number=3; これはobjのプロパティnumberを指します.
同じように2番目のconsole.log印刷もプロパティnumberです.
なぜ第二に、一般的にはthisは関数の所有者を指しているのか.特別な状況があるからだ.関数の自己実行は特殊な場合で、関数の自己実行の中で、thisはwindowを指します.だから最初のconsole.logはwindowのプロパティnumberを印刷します.
だから少し追加します.
3. 関数の自己実行では、thisはwindowオブジェクトを指します.
拡張、thisについて、domイベントでは、通常次の3つのケースがあります.
次のようになります.
1. ラベルプロパティを使用してイベントを登録します.この場合、thisはwindowオブジェクトを指します.
function test(){alert(this)}
2. 1の場合、thisをinputに向けるには、thisをパラメータとして渡すことができます.
3. addEventListenerなどを使用して登録します.このときthisもinputを指します.
document.getElementById("test").addEventListener("click",test);
オブジェクト向けプログラミング言語では、thisキーワードについてよく知られています.例えばC++、C#、Javaなどがこのキーワードを提供しているので、勉強を始めるときは難しいと思いますが、理解さえすれば、とても便利で意味が確定します.JavaScriptもこのthisキーワードを提供していますが、古典的なOO言語よりも「混乱」しています.
次に、JavaScriptでのthisの使い方の乱れを見てみましょう.
1、HTML要素イベント属性においてinline方式でthisキーワードを使用する:
// this
">division element
// this
">division element
一般的によく使われる方法は、javascirpt:EventHandler(this)という形式です.しかし、ここでは合法的なJavaScript文を書くことができます.ここでクラスを定義してもいいです(ただし、内部クラスになります).ここでの原理は、スクリプトエンジンがdivインスタンスオブジェクトの匿名メンバーメソッドを生成し、onclickがこのメソッドを指すことである.
2、DOM方式でイベント処理関数にthisキーワードを使用する:
division element
var div = document.getElementById('elmtDiv');
div.attachEvent('onclick', EventHandler);
function EventHandler()
{
// this
}
// -->
division element
var div = document.getElementById('elmtDiv');
div.attachEvent('onclick', EventHandler);
function EventHandler()
{
// this
}
// -->
このときのEventHandler()メソッドのthisキーは,IEのwindowオブジェクトを示す.これはEventHandlerが一般的な関数にすぎず、attachEventの後、スクリプトエンジンはその呼び出しとdivオブジェクト自体に何の関係もないためです.また、nullに等しいEventHandlerのcallerプロパティも参照できます.この方法でdivオブジェクト参照を取得する場合は、thisを使用します.event.srcElement.
3、DHTML方式でイベント処理関数でthisキーワードを使用する:
division element
lt;mce:script language="javascript">
var div = document.getElementById('elmtDiv');
div.onclick = function()
{
// this
};
/ -->
division element
var div = document.getElementById('elmtDiv');
div.onclick = function()
{
// this
};
// -->
ここでthisキーはdiv要素オブジェクトインスタンスを示し、スクリプトでDHTML方式を使用してdiv.onclickに直接EventHandlerを割り当てる方法であり、divオブジェクトインスタンスにメンバーメソッドを追加することに等しい.この方式と第1の方法の違いは、第1の方法はHTML方式を使用することであり、ここではDHTML方式であり、後者のスクリプト解析エンジンは匿名の方法を生成しない.
4、クラス定義でthisキーワードを使用する:
function JSClass()
{
var myName = 'jsclass';
this.m_Name = 'JSClass';
}
JSClass.prototype.ToString = function()
{
alert(myName + ', ' + this.m_Name);
};
var jc = new JSClass();
jc.ToString();
function JSClass()
{
var myName = 'jsclass';
this.m_Name = 'JSClass';
}
JSClass.prototype.ToString = function()
{
alert(myName + ', ' + this.m_Name);
};
var jc = new JSClass();
jc.ToString();
これはJavaScriptシミュレーションクラス定義におけるthisの使用であり,これは他のOO言語の場合と非常によく知られている.ただし、ここではメンバーのプロパティとメソッドをthisキーで参照する必要があります.上記のプログラムを実行するとmyNameが定義されていないことが通知されます.
5、スクリプトエンジンの内部オブジェクトに原形メソッドのthisキーワードを追加する:
function.prototype.GetName = function()
{
var fnName = this.toString();
fnName = fnName.substr(0, fnName.indexOf('('));
fnName = fnName.replace(/^function/, '');
return fnName.replace(/(^\s+)|(\s+$)/g, '');
}
function foo(){}
alert(foo.GetName());
function.prototype.GetName = function()
{
var fnName = this.toString();
fnName = fnName.substr(0, fnName.indexOf('('));
fnName = fnName.replace(/^function/, '');
return fnName.replace(/(^\s+)|(\s+$)/g, '');
}
function foo(){}
alert(foo.GetName());
ここでthisとは、原形が追加されたクラスの例を指し、4のクラス定義と少し似ていて、あまり特別なところはありません.
6、2&4を組み合わせて、迷っているthisキーワードを使います.
view plaincopy to clipboardprint?
function JSClass()
{
this.m_Text = 'division element';
this.m_Element = document.createElement('DIV');
this.m_Element.innerHTML = this.m_Text;
this.m_Element.attachEvent('onclick', this.ToString);
}
JSClass.prototype.Render = function()
{
document.body.appendChild(this.m_Element);
}
JSClass.prototype.ToString = function()
{
alert(this.m_Text);
};
var jc = new JSClass();
jc.Render();
jc.ToString();
function JSClass()
{
this.m_Text = 'division element';
this.m_Element = document.createElement('DIV');
this.m_Element.innerHTML = this.m_Text;
this.m_Element.attachEvent('onclick', this.ToString);
}
JSClass.prototype.Render = function()
{
document.body.appendChild(this.m_Element);
}
JSClass.prototype.ToString = function()
{
alert(this.m_Text);
};
var jc = new JSClass();
jc.Render();
jc.ToString();
結果についてお話ししますと、ページが実行されると「division element」と表示され、確定したら「division element」という文字をクリックすると「undefined」と表示されます.
7、CSSのexpression式でthisキーワードを使用する:
height: expression(this.parentElement.height);">
division element
height: expression(this.parentElement.height);">
division element
ここでthisは1と同様にすればよいと考えられ、div要素オブジェクトインスタンス自体を指す.
8、関数の内部関数でthisキーを使用する:
view plaincopy to clipboardprint?
function OuterFoo()
{
this.Name = 'Outer Name';
function InnerFoo()
{
var Name = 'Inner Name';
alert(Name + ', ' + this.Name);
}
return InnerFoo;
}
OuterFoo()();
function OuterFoo()
{
this.Name = 'Outer Name';
function InnerFoo()
{
var Name = 'Inner Name';
alert(Name + ', ' + this.Name);
}
return InnerFoo;
}
OuterFoo()();
実行結果は、「Inner Name,Outer Name」と表示されます.2の説明では、ここの結果が「Inner Name,undefined」ならもっと合理的なようですね?しかし、正確な結果は確かに前者であり、これはJavaScript変数の役割ドメインの問題によって決定されたものであり、「元のJscriptのキーワード「var」には文章があるのか」の一文と返事を詳しく理解することを推奨する.
まとめてみると、JavaScriptのthisの使い方は、以下の3つあります(詳しくは原文参照).
1.HTML要素イベント属性またはCSSのexpression式でinline方式でthisキーワードを使用――原文の1、7に対応
2.イベント処理関数にthisキーを使用――原文に対応する2,3
このうち2つの方法に分けることができます
(1)DOM方式――この方式の結果はthisがウィンドウオブジェクトを指す
(2)DHTML方式――この方式の結果、thisがdiv要素オブジェクトを指す例
3.クラス定義でthisキーワードを使用し、その内部関数またはメンバー関数(主にprototype生成)で使用します.原文の4、5、8に対応します.
なお、関数でもオブジェクトであるため、次のように変数定義とメンバー変数定義を区別する必要があります.
view plaincopy to clipboardprint?
var variableName; //
// :
// : variableName
this.varName; //
// :
// :this.varName
var variableName; //
// :
// : variableName
this.varName; //
// :
// :this.varName
以上まとめた3種類のthisの使用方法のうち、1つ目は比較的理解しやすく、ここでは原文の6点に記載のプログラムをテストし、以下のように改善し、上記の2つの使用方法を説明した.
view plaincopy to clipboardprint?
function JSClass()
{
var varText = "func variable!"; //
this.m_Text = 'func member!'; //
this.m_Element = document.createElement('DIV'); // , div
this.m_Element.innerHTML = varText; //
this.m_Element.attachEvent('onclick', this.ToString); //
this.newElement = document.createElement('DIV');
this.newElement.innerHTML = "new element";
this.newElement.m_Text = "new element text!"; //
this.newElement.onclick = function()
{
alert(this.m_Text); // div
};
}
JSClass.prototype.Render = function()
{
document.body.appendChild(this.m_Element); // div
document.body.appendChild(this.newElement);
}
JSClass.prototype.ToString = function()
{
alert(this.m_Text); // (window)
};
function initialize(){
var jc = new JSClass();
jc.Render();
jc.ToString(); // this JSClass , m_Text
}
// -->
initialize();
// -->
function JSClass()
{
var varText = "func variable!"; //
this.m_Text = 'func member!'; //
this.m_Element = document.createElement('DIV'); // , div
this.m_Element.innerHTML = varText; //
this.m_Element.attachEvent('onclick', this.ToString); //
this.newElement = document.createElement('DIV');
this.newElement.innerHTML = "new element";
this.newElement.m_Text = "new element text!"; //
this.newElement.onclick = function()
{
alert(this.m_Text); // div
};
}
JSClass.prototype.Render = function()
{
document.body.appendChild(this.m_Element); // div
document.body.appendChild(this.newElement);
}
JSClass.prototype.ToString = function()
{
alert(this.m_Text); // (window)
};
function initialize(){
var jc = new JSClass();
jc.Render();
jc.ToString(); // this JSClass , m_Text
}
// -->
initialize();
// -->
上記のコードの実行結果は、次のとおりです.
ページがロードされると、ダイアログボックスがポップアップされ、func memberが出力されます.
ページに表示
func variable!
new element
func variableをクリックすると、ポップアップダイアログボックスが開き、undefinedが表示されます.
――このときtoString関数のthisポインタがwindowを指しているため
new elementをクリックすると、ポップアップダイアログボックスにnew element textが表示されます.
――toString関数のthisポインタがdiv要素を指しているため、この要素はm_を定義しています.Textメンバー(this.newElement.m_Text="new element text!")