JavaScript このキーワードの使用分析_JavaScript スキル

WBOY
リリース: 2016-05-16 18:59:46
オリジナル
885 人が閲覧しました

js には this キーワードに関する多くの記事があり、そのいくつかを読みましたが、この記事を書く目的は、このキーワードの動作原理を例から分析することです。

1. 基本:

コードをコピーします コードは次のとおりです:

function doSomething(){
alert(this.id);
}
alert(window.doSomething);// doSomething が wi​​ndow に属していることを証明します
doSomething();//未定義
window.onload = function(){
document.getElementById("div2").onclick = doSomething;//div2
document.getElementById("div3").onclick = function(){doSomething ( );}//未定義
}

1. doSomething 関数の場合:
コードをコピーします コードは次のとおりです。

function doSomething(){
alert(this.id);
}

この関数はグローバル関数、this グローバル関数は実際には window に属します (window.doSomething を通じてアクセスできます)。「this は常に実行している関数の "所有者" を参照します」に従って、 this になります。ただし、window には id 属性がないため、

2. HTML 要素内でこれを呼び出します。 🎜>コードをコピー
コードは次のとおりです:
div1
この「未定義」も表示されます。これは次のコードと同等です:



コードをコピー
div1 をクリックすると、ウィンドウに属する doSomething 関数が呼び出されるため、「未定義」も表示されます。

3. div2 が読み込まれた後、イベントをバインドします。
コードをコピーします


コードは次のとおりです。
document.getElementById("div2").onclick = doSomething; 🎜> div2 をクリックすると、div2 の onclick に一度値が代入されているため、「div2」と表示されます。このとき、コピーされた関数は div2 に属しており、window に属する doSomething とは関係ありません。 。 div2 をクリックすると、div2 に属する doSomething がトリガーされます。これは、div2 を指します。 2.attachEvent と addEventListener attachEvent は、IE のイベントをバインドするメソッドです (つまり、応答関数の所有者は window)。ただし、DOM 標準では、addEventListener がイベントをバインドするとき、コピーされた応答関数の所有者はイベントにバインドされたオブジェクトです


コードをコピー


コードは次のとおりです。


function doSomething(){
alert(this.id); alert(this == window); >window.onload = function(){ var div1 = document.getElementById("div1"); if(div1.attachEvent){ div1.attachEvent("onclick",doSomething); >document.body.appendChild(document.createTextNode ("attachEvent")); }else if(div1.addEventListener){ div1.addEventListener("click",doSomething,false); body.appendChild(document.createTextNode("addEventListener "));
}else{
div.onclick = doSomething;
}
}



function doSomething




コードをコピー


コードは次のとおりです。


function doSomething(){
alert(this.id);
alert(this == ウィンドウ)


1. addEventを使用してdiv1のクリックイベントにバインドします。このとき、doSomethingのthisはdiv1をクリックしたときに「unknown」と「true」を参照します。

2. addEventListenerを使ってdiv1のクリックイベントをバインドします。このとき、コピーした関数はdiv1に属しているので、div1をクリックすると「div1」と「false」が表示されます。 🎜>
注: http://www.quirksmode.org/js/this.html では、attachEvent は単に関数参照を使用していると考えられます。次のコードを参照してください:

<🎜。 >コードをコピーします コードは次のとおりです:
var obj = new Object();
obj.color = "black"; .showColor = function(){
alert(this == window);
obj.showColor();

var div1 = document.getElementById("div1");
div1.attachEvent("onclick",obj.showColor);


このとき div1 をクリックすると、「unknown」と「true」が表示されます。表示される場合、attachEvent が obj.showColor のみを参照する場合、これは引き続き obj を参照する必要がありますが、実際にはこれは window を参照するため、これは参照ではなく、グローバルなものへのコピーだと思います。

3. オブジェクト偽装の継承方法について
1. new と not new の違い

以下の関数について




コードをコピーします
コードは次のとおりです。 function ClassA(sColor){ this.color = this; .sayColor = function() {
alert(this.color);
}
}


これはクラスですか、それとも関数ですか?それはあなた次第です!

これが関数だと思う場合は、次のように呼び出すことができます:
ClassA("red");
"red" は ClassA で渡されるパラメータです。もちろん、window には color 属性とsayColor メソッドがあり、color の値は「red」になります。

これは、sayColor または window.sayColor を呼び出して "red" を表示します。


これがクラスだと思うなら、

var obj = new ClassA("red");
new キーワードの出現により、上記のコードに多くの内容が追加されます。 まず、Object インスタンスを作成します。 、次に、ClassA の this が作成された Object を指すようにし、最後にこの Object を返すため、返された Object は obj に割り当てられます。したがって、これは obj を指しており、obj には color 属性とsayColor メソッドがあり、color 属性値は「red」であると言えます。

2. 関数所有者




コードをコピーします


コードは次のとおりです:
function showId(){ alert(this.id); } window.onload = function(){ var div1 = document.getElementById("div1"); .onclick = showId;
div1.show();

var obj = "obj"; >obj .show = showId;
obj.show();
}


これにより、showId 関数を任意のオブジェクトの任意の属性に割り当てることができます。 showId メソッドもコピーします。つまり、div1.show メソッドを呼び出すと、これは div1 を指し、obj.show を呼び出すと、これは obj を指します。

3. オブジェクト偽装の原理

次のコードはオブジェクト偽装メソッドによって実装された継承です




コードをコピー


コードは次のとおりです。


function ClassA(sColor){
this.color = sColor; alert(this.name);

var objB = new ClassB("objB の色","objB の名前");
objB.sayColor();
objB は ClassB のインスタンスです。objB はどのようにして color 属性とsayColor メソッドを持っていますか?

まずインスタンス化コードを見てみましょう:

var objB = new ClassB("color of objB","name of objB");

ここで ClassB はクラスです。もちろん、ClassB では、これはオブジェクト objB を参照します。

ClassB では、コードの最初の 3 行で ClassA が使用され、ClassA はクラスではなく関数とみなされます。

ClassA 関数を直接呼び出すと、明らかに ClassA の this は window オブジェクトを参照するため、最初に ClassA を objB の newMethod 属性 (this.newMethod = ClassA) にコピーします。

次に、 this.newMethod を呼び出します。 これは、このメソッドの所有者が明らかに this になっており、 ClassB の this は現在 objB を参照しているため、この時点では ClassA にあります (これはコピーされているため、厳密には newMethod にあります)。すでに ClassA に 2 つのメソッドがあります) これは objB を参照します。このようにして、newMethod の呼び出しを通じて、color 属性と SayColor メソッドが objB に割り当てられます。 call メソッドと apply メソッドを使用して継承を実装するのは実際には原則であり、call および apply はメソッドの所有者を変更するメソッドとみなすことができ、ここでの ClassB の最初の 3 行のコードがこの役割を果たします。

4.prototype1.6 の Class.create
コードをコピー コードは次のとおりです。

prototype1.6 の Class.create メソッドはおおよそ次のとおりです:

var Class = {
create: function() {
//

function klass() {
this.initialize.apply(this, argument);
}

//

for (var i = 0; i klass.addMethods(properties[i])

return
}
}; > 使用中 次のようになります:





コードをコピー
コードは次のとおりです: var person = Class.create({ initialize:function(name){ this.name = name;
},
say:function(message){
alert(this.name " :" message);

var aperson = new Person("name1");


person は、実際には Class.create メソッドによって返される klass (klass は Class.create のローカル変数、関数) であり、Class.create (initialize メソッドと Say メソッド) によって渡されるパラメータです。 ) がメソッドのプロパティ配列の作成に渡され、addMethods メソッドを通じて klass プロトタイプにこれらのメソッドを持たせます。したがって、最も重要な点であり、理解するのが最も難しいのは、「klass の this が正確に何を指すのか」ということです。よく考えてみれば、その答えを得るのは難しくありません。実際には person は klass であり、person オブジェクトをインスタンス化するときは、次の new キーワードを使用します:

var aperson = new Person("name1") ) ;

これは

var aperson = new klass("name1");

からは簡単にアクセスできます。この方法で問題を説明すると、klass は単純な関数ではなくクラスです (new キーワードが使用されているため、そう考えられます)。klass の this は宣言されたインスタンスを指します。ここでは aperson で、aperson は klass のプロトタイプを渡します。新しいプロセス中に、klass 内のコードも実行されるため、initialize はインスタンス化、つまりコンストラクターのときに実行されます。 (klass のこれは両方とも aperson を参照します。なぜ apply を通じて一度呼び出す必要があるのですか? これは主にコンストラクターのパラメーターを渡すためです。 apply メソッドを使用すると、配列を介して初期化するために無限の数のパラメーターを簡単に渡すことができます。 .メソッド。)

5. さらにいくつかの例を分析します。

1. 次のように実行します。 🎜>


コードをコピーします


コードは次のとおりです:


function innerFoo(){
this.Name = '外部名';
function InnerFoo(){ var Name = '内部名'; alert(Name ', ' this.Name); return InnerFoo; } OuterFoo()();

表示される結果は「内部名、外部名」です。

OuterFoo は関数 (クラスではありません) であり、最初の文は

this.Name = 'Outer Name'; in

は window オブジェクトを参照しているため、OuterFoo() の後 window.Name = 'Outer Name';

を返し、この時点では InnerFoo も関数です (クラスではありません)。 )、InnerFoo を実行するとき、これは window も参照するため、InnerFoo の this.Name の値は「Outer Name」になります (window.Name は転送ステーションとして機能し、OuterFoo が値「Outer Name」を InnerFoo に渡すことができます)。 Name の値はローカル変数 "Inner Name" です

2. 次のコードを実行します


コードをコピー コードは次のとおりです。

function JSClass(){

this.m_Text = '分割要素';
this.m_Element = document .createElement( 'DIV');
this.m_Element.innerHTML = this.m_Text;

if(this.m_Element.attachEvent)
this.m_Element.attachEvent('onclick', this. ToString);
else if(this.m_Element.addEventListener)
this.m_Element.addEventListener('click', this.ToString,false);
else
this.m_Element.onclick = this。 ToString;
}

JSClass.prototype.Render = function(){
document.body.appendChild(this.m_Element);

JSClass.prototype。 ToString = function (){
alert(this.m_Text);
alert(this == window)
}

window.onload = function(){
var jc = new JSClass ();
jc.ToString();
}


「分割要素」をクリックすると、「未定義」と表示されます。 IE でも必須です。 「true」が表示され、他のブラウザでも「false」が表示されます。

要素のクリック イベントはインスタンス メソッドにバインドされているため、addEventListener を通じてバインドされたメソッドがコピーされるため、これは HTML 要素を指します。この要素には m_Text 属性がないため (m_Text 属性は JSClass のインスタンス、つまり jc に属します)、この要素をクリックすると、attachEvent にバインドされたイベントが関数をグローバル ワールドにコピーします。要素をクリックすると、これはウィンドウ オブジェクトを指します。また、「未定義」と表示されます。 jc.ToString()メソッドが呼び出された場合のみ、jcオブジェクトを参照します。jcはm_Textを所有しているため、「分割要素」を表示できます。

6. 概要

コード環境で this が指すオブジェクトを素早く見つけるにはどうすればよいでしょうか?次の 3 つの点に注意してください。
1. 関数の各ステップがコピーなのか参照 (呼び出し) なのかを明確に知る必要があります。
2. 誰が実行しているのかを明確に知る必要があります。関数の所有者は
3. 関数の場合、それを関数として使用しているかクラスとして使用しているかを判断する必要があります

補足:
1 で関数を直接定義できます。インスタンスとクラスの両方
2. プロトタイプを使用してインスタンスの関数を定義することはできません。クラスで直接定義された関数は、これを使用してオブジェクトのプロパティにアクセスすることはできません。
4. クラスのプロトタイプ上で作成された関数はこれを使用でき、クラス内で定義された関数はこれを使用でき、オブジェクト インスタンスで作成された関数はこれを使用できます。



コピーcode コードは次のとおりです。 window.alert=function (msg)
{
document.write(msg "
");
}
function Say()
{
this.f="props";
this.func3=function(){alert("f3," this.f) ;}
}
say .func1=function(){alert("func1," this.f);}; //エラー、クラスで直接定義された関数はこの
say.prototype では使用できません.func2=function(){alert(" func2," this.f);}
say.func1();
(新しいsay()).func2(); ; //エラー、プロトタイプ関数で定義されています。
say.func3() を呼び出す前にオブジェクトをインスタンス化する必要があります。 //エラー、
(new Say()) を呼び出す前に、クラスで定義された関数をインスタンス化する必要があります。 .func3();
var obj={
fld1:10,
func1:function(msg){alert(msg);},
func4:function(){alert(this.fld1) );}
}
obj.prototype.func=function(){alert("func");}; //エラー プロトタイプはインスタンス オブジェクトのオブジェクトの定義に使用できません
obj.func2=function (){alert("func2, this .fld1);}; //OK、インスタンス上で直接定義された関数はこれを使用してオブジェクト
alert(obj.fld1);
obj のプロパティにアクセスできます。 .func1("func1");
obj .func2();


Javascript this usage summary
http://www.jb51.net/article/16863.htm

JavaScript this in-depth understanding
http://www.jb51.net/article/19425.htm

JAVASCRIPT THIS detailed explanation object-oriented
http://www.jb51.net/article/17584.htm

Javascript this pointer
http://www.jb51.net/article/19434.htm

Detailed explanation of how to use this keyword in JavaScript
http://www.jb51.net/article/7954.htm

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート