9

関連する質問#1#2を読んだ後で も、次の質問に対する答えが見つかりません。

Javascript は、 、およびを使用してコンテキストを設定 (つまり、 set this) できます。bindcallapply

しかし、私がイベントハンドラを書いているとき:

document.getElementById('myInput').onclick = function ()
                                                   {
                                                      alert(this.value)
                                                   }

誰/何が自分自身に実際に付着 thisobjectますか?

PS jQuery を使用する場合:

  $("#myInput").bind(function (){...})

( 、または)の内部実装がありますbindcallapply

では、 jQuery を使用していないときは、誰が使用しているのでしょうか?

4

7 に答える 7

8

もちろん、DOM/JavaScript は、W3C によってそのように動作するはずです。

イベント ハンドラーは、特定のオブジェクト (現在のイベント ターゲット) のコンテキストで呼び出され、イベント オブジェクト自体と共に提供されます。

ソース

それがどのように正確に起こるかはわかりません。実装の詳細です。

私たちが知っているのは、W3C によって定義されたセマンティクスが何らかの方法で達成されるということだけですが、ブラウザーのどの部分がどのようにそれを行うかは、ブラウザー開発者に任されており、適切と思われる方法で実装できます。

于 2012-10-04T08:08:20.947 に答える
2

すべての議論を要約するには:

  • 一般に、呼び出されたときに関数呼び出し内にバインドするのは JavaScriptthisです。oo.x()
  • ただし、この動作を変更する関数 (f.apply()や など)を呼び出す代替方法がいくつかあります。f.call()
  • onclickは特殊なケースであり、それを呼び出すために使用されるメソッドは不明であり、DOM 実装に依存します。
于 2012-10-04T08:55:20.037 に答える
1

あなたの例では、onclickハンドラーのそれは完全に簡単です.DOM要素オブジェクトであり、onclickプロパティを関数として定義しています. その関数は事実上、その DOMElement/オブジェクトのメソッドになります。そのオブジェクトがクリックされると、関数はその要素のメソッドとして呼び出されるため、 this はその所有者
である要素を指します。

簡単に言えば、関数オブジェクトへの参照が別のオブジェクトに割り当てられていない限り、関数が実行されるコンテキストは、作成されたコンテキストと同じです (繰り返しますが、DOM 要素のメソッドとしての例では)。その関数オブジェクトcallがor apply& coを使用して別のコンテキストで呼び出されたとき。
もちろん、これにはもう少し多くのことがあります: 上でほのめかしたように、関数はそれ自体がオブジェクトであり、それらの「所有者」に疎結合されていると言われています。実際には、関数が呼び出されるたびに、そのコンテキストが決定されます。

var foo = someObject.someFunction;//reference to method
someObject.someFunction();//this === someObject, context is the object preceding the function
foo();//implies [window].foo(); ==> this is window, except for strict mode

@wroniasty が指摘したように、所有権についての私の話は少し混乱するかもしれません。問題は、関数はオブジェクトであり、何にも所有されていないということです。オブジェクトにメソッドが割り当てられると、そのオブジェクトが実際に所有するのは、特定の関数オブジェクトへの参照だけです。その関数がその参照を介して呼び出されるとthis、呼び出し元の参照を所有していたオブジェクトを指します。
これを に適用するとelem.onclick = function(){}、要素が何らかのスコープで宣言された関数式への参照のみを所有していることがわかります (グローバル、名前空間オブジェクトは関係ありません)。クリック イベントが発生すると、その参照を使用してハンドラーが呼び出され、要素への参照が に割り当てられthisます。明確にするために:

document.getElementById('foo').onclick = (function()
{//This function returns the actual handler
    var that = this;//closure var
    console.log(this);//logs window object
    //defined in global context
    return function(e)//actual handler
    {
        console.log(this === that);//false
        console.log(this);//elem
        console.log(that);//window
    };
})();//IIFE

そのため、ハンドラーはグローバル コンテキストで宣言され、thatクロージャーのおかげで、ハンドラーは using で宣言されたコンテキストにアクセスできます (ただし、それは別の話です)。ポイントは、イベントonclickが element のプロパティを使用してハンドラを参照することfooです。そのプロパティは関数オブジェクトへの参照であるため、関数オブジェクトはそのコンテキストを、呼び出しを行ったオブジェクトに設定します。

これにより、関数の所有権、およびおそらく JS のコンテキストがどのように決定されるかに関して私が引き起こした混乱が解消されることを願っています。

于 2012-10-04T08:11:12.847 に答える
1

それがDOMであるという答えは間違っています。

これは、言語としての JavaScript 自体の一部です。DOM は、名前が「ドキュメント オブジェクト モデル」を示すものにすぎません。これは、JavaScript を使用して操作するために HTML を表現する方法です。DOM に関連するオブジェクトは標準で規定された動作に従いますが、これは JS を使用して実装されます。これを行うのは JS エンジンであり、使用されているレイアウト エンジン (Gecko、Trident、WebKit、Presto など) と通信します。そのため、WebKit がイベントを検出すると、DOM 仕様が示すように、それを JS エンジンに渡し、JS プログラマーが操作できるようにします (これが、あなたがこれについて質問している理由です。操作できるからです)。

つまり、JavaScript で何かを記述している場合、それを読み取って実行する方法を理解できる唯一のエンジンは JS エンジンです。このエンジン (v8、SpiderMonkey/Jugger/Trace) は、レイアウト エンジンからデータを受け取り、それを使用して操作できるようにします。同様に、レイアウトに影響を与えるコードを実行すると、レイアウト エンジンによって変更が検出され、ユーザーが変更を認識できるようにレイアウトが変更されます。JS コードがこれを開始したとしても、レイアウトを処理するレイアウト エンジンです。

関数をオブジェクトに割り当てるときの「これ」とは、単に関数が属する場所です。したがって、関数をオブジェクト a のインスタンスに割り当てると、その関数は、その中で「this」を使用するたびに a を参照します。

実装の用語で考えたい場合は、次のように考えてください。メソッドを呼び出すときはいつでも、最初にインスタンスに、N 個のパラメーターでメソッドを呼び出したいことを伝えます。このインスタンスはメソッドを呼び出しますが、それ自体を「this」としてコンテキストに追加します。

Python では、すべてのインスタンス メソッドの最初のパラメーターをインスタンス自体にすることで、これをより明示的に行います。ここでも同じですが、インスタンスは明示的ではなく暗黙的に渡されます。

インスタンスがメソッドを所有していることを思い出してください。「document.getElementById('something')」を実行すると、呼び出しによってオブジェクトが返されます (たまたま DOM の一部である HTMLElement オブジェクトですが、これは JS が DOM と対話する方法と一致しています)。プロパティクリックとしての機能。

次に、メソッドを呼び出すたびに、JavaScript エンジンは、他の変数を渡すのと同じように、デフォルトでインスタンスを渡します (同様に、何もしなくても引数が生成されます。これも、ECMAScript 標準を実装する JS エンジンによって行われます)。

63ページをチェックすることをお勧めします:

「 this キーワードは、現在の実行コンテキストの ThisBinding の値に評価されます。」

しかし、最も重要なことは、68ページの「関数呼び出し」です。

http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf

于 2012-10-04T08:17:02.077 に答える
0

http://dmitrysoshnikov.com/ecmascript/chapter-3-this/#this-value-in-the-function-code

基本的に、JavaScript 内部で行われます。

コンテキストは、関数を呼び出すオブジェクトです。

elem.onclick();  // elem === this

でも:

func = elem.onclick;
func() // global === this
于 2012-10-04T08:13:25.800 に答える
0

前述のように、これは実際には DOM とは関係ありませんが、オブジェクト内で関数を呼び出すときに JavaScript がどのように機能するように設計されているかということです。

これを例にとります:

var myObject = {
    id: 1,
    onclick: null
}

myObject.onclick = function() {
    console.log(this.id);
}

呼び出しはコンソールにmyObject.onclick()記録されます。つまり、そのコンテキストです。1myObject

onclickはオブジェクトのプロパティでもあるためthis、親オブジェクトになります。この場合はHTMLElement.

于 2012-10-04T08:12:33.897 に答える
0

説明のために、実装は異なる場合がありますが、次の関数を考えてください。

 function f() { alert(this.name); } 

なので

function f(this) { alert(this.name); } 

これは、bind、apply、call でオーバーライドできるが、通常はブラウザーによって呼び出し元オブジェクトに設定されるシークレット パラメーターであると想像してください。

var a = {},
    b = {};

a.name = "John";
b.name = "Tom";

// "this" param added secretly
function printName( ) { 
    console.log( this.name ) 
};

a.printName = printName     
b.printName = printName;

printName 関数を呼び出すと、ブラウザーはこのパラメーターを呼び出し元の関数に「秘密」に設定します。以下の例では、これは b であるため、"Tom" がコンソールに出力されます。

printName( ); // global context assumed so this === window
b.printName( ); // this === b and outputs "Tom"
printName.call( a ); //this === a and outputs "John"

詳細はこちら

于 2012-10-04T08:17:13.520 に答える