この記事では、js での this の使用法を分析する例を使用します。次の例からわかるように、obj.foo() の場合、foo は obj 環境で実行されます。したがって、これは obj を指します。foo() の場合、foo はグローバル環境で実行されるため、これはグローバル環境を指します。したがって、両者の経営成績は異なります。これが決定的な役割を果たしていることがわかります。この記事が皆さんの参考値になれば幸いです。
JavaScript 言語を学習するには、異なる結果をもたらす可能性がある次の 2 つの記述方法を理解することが 1 つの兆候です。
var obj = { foo: function () {} }; var foo = obj.foo; // 写法一 obj.foo() // 写法二 foo()ログイン後にコピー
上記のコードでは、obj.foo
と foo
は同じ関数を指していますが、実行結果は異なる場合があります。以下の例を参照してください。 obj.foo
和foo
指向同一个函数,但是执行结果可能不一样。请看下面的例子。
var obj = { foo: function () { console.log(this.bar) }, bar: 1 }; var foo = obj.foo; var bar = 2; obj.foo() // 1 foo() // 2ログイン後にコピー
这种差异的原因,就在于函数体内部使用了this
关键字。很多教科书会告诉你,this
指的是函数运行时所在的环境。对于obj.foo()
来说,foo
运行在obj
环境,所以this
指向obj
;对于foo()
来说,foo
运行在全局环境,所以this
指向全局环境。所以,两者的运行结果不一样。
这种解释没错,但是教科书往往不告诉你,为什么会这样?也就是说,函数的运行环境到底是怎么决定的?举例来说,为什么obj.foo()
就是在obj
环境执行,而一旦var foo = obj.foo
,foo()
就变成在全局环境执行?
本文就来解释 JavaScript 这样处理的原理。理解了这一点,你就会彻底理解this
的作用。
JavaScript 语言之所以有this
的设计,跟内存里面的数据结构有关系。
var obj = { foo: 5 };ログイン後にコピー
上面的代码将一个对象赋值给变量obj
。JavaScript 引擎会先在内存里面,生成一个对象{ foo: 5 }
,然后把这个对象的内存地址赋值给变量obj
。
也就是说,变量obj
是一个地址(reference)。后面如果要读取obj.foo
,引擎先从obj
拿到内存地址,然后再从该地址读出原始的对象,返回它的foo
属性。
原始的对象以字典结构保存,每一个属性名都对应一个属性描述对象。举例来说,上面例子的foo
属性,实际上是以下面的形式保存的。
{ foo: { [[value]]: 5 [[writable]]: true [[enumerable]]: true [[configurable]]: true } }ログイン後にコピー
注意,foo
属性的值保存在属性描述对象的value
属性里面。
这样的结构是很清晰的,问题在于属性的值可能是一个函数。
var obj = { foo: function () {} };ログイン後にコピー
这时,引擎会将函数单独保存在内存中,然后再将函数的地址赋值给foo
属性的value
属性。
{ foo: { [[value]]: 函数的地址 ... } }ログイン後にコピー
由于函数是一个单独的值,所以它可以在不同的环境(上下文)执行。
var f = function () {}; var obj = { f: f }; // 单独执行 f() // obj 环境执行 obj.f()ログイン後にコピー
JavaScript 允许在函数体内部,引用当前环境的其他变量。
var f = function () { console.log(x); };ログイン後にコピー
上面代码中,函数体里面使用了变量x
。该变量由运行环境提供。
现在问题就来了,由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。所以,this
就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。
var f = function () { console.log(this.x); }ログイン後にコピー
上面代码中,函数体里面的this.x
就是指当前运行环境的x
。
var f = function () { console.log(this.x); } var x = 1; var obj = { f: f, x: 2, }; // 单独执行 f() // 1 // obj 环境执行 obj.f() // 2ログイン後にコピー
上面代码中,函数f
在全局环境执行,this.x
指向全局环境的x
。
在obj
环境执行,this.x
指向obj.x
この違いの理由は、 this
キーワードが関数本体内で使用されているためです。多くの教科書では、this
が関数が実行される環境を指すと説明されています。 obj.foo()
の場合、foo
は obj
環境で実行されるため、this
は obj を指します。
; foo()
の場合、foo
はグローバル環境で実行されるため、this
はグローバル環境を指します。したがって、両者の経営成績は異なります。
obj.foo()
が obj
環境で実行され、一度 var foo = obj.foo
, foo ()
はグローバル環境で実行されますか? 🎜🎜この記事ではこのようなJavaScriptの処理原理を解説していきます。これを理解すると、this
の役割を完全に理解できるようになります。 🎜🎜2. メモリのデータ構造🎜🎜 JavaScript 言語が this
の設計になっている理由は、メモリ内のデータ構造に関係しています。 🎜🎜rrreee🎜🎜上記のコードは、オブジェクトを変数 obj
に割り当てます。 JavaScript エンジンは、まずメモリ内にオブジェクト { foo: 5 }
を生成し、次にこのオブジェクトのメモリ アドレスを変数 obj
に割り当てます。 🎜🎜🎜🎜つまり、変数obj
はアドレス(参照)です。後で obj.foo
を読み取りたい場合、エンジンはまず obj
からメモリ アドレスを取得し、次にそのアドレスから元のオブジェクトを読み取り、その foo プロパティ。 🎜🎜元のオブジェクトは辞書構造に保存され、各属性名は属性説明オブジェクトに対応します。たとえば、上記の例の <code>foo
属性は、実際には次の形式で保存されます。 🎜🎜🎜🎜rrreee🎜🎜注意の場合、foo
属性の値は、属性説明オブジェクトの value
属性に格納されます。 🎜🎜3. 関数 🎜🎜 この構造は非常に明確ですが、問題は属性の値が関数である可能性があることです。 🎜🎜rrreee🎜🎜このとき、エンジンは関数をメモリに個別に保存し、関数のアドレスを foo
属性の value
属性に割り当てます。 。 🎜🎜🎜🎜rrreee🎜🎜期限関数は単一の値であるため、さまざまな環境 (コンテキスト) で実行できます。 🎜🎜rrreee🎜🎜4. 環境変数🎜🎜JavaScript では、関数本体内で現在の環境の他の変数を参照できます。 🎜🎜rrreee🎜🎜 上記のコードでは、変数 x
が関数本体で使用されています。この変数はランタイム環境によって提供されます。 🎜🎜ここで問題が発生します。関数はさまざまな実行環境で実行できるため、関数本体内に現在の実行環境 (コンテキスト) を取得するメカニズムが必要です。したがって、this
が表示されるのは、関数本体内の関数の現在の実行環境を参照することです。 🎜🎜rrreee🎜🎜 上記のコードでは、関数本体の this.x
は、現在の実行環境の x
を参照しています。 🎜🎜rrreee🎜🎜 上記のコードでは、関数 f
がグローバル環境で実行され、 this.x
はグローバル環境の x
を指します。環境。 🎜🎜🎜🎜in obj
環境の実行、this.x
は obj.x
を指します。 🎜🎜🎜🎜この記事の冒頭で挙げた質問に戻りますが、obj.foo()
是通过obj
找到foo
,所以就是在obj
环境执行。一旦var foo = obj.foo
,变量foo
就直接指向函数本身,所以foo()
はグローバル環境で実行されます。
関連する推奨事項:
以上がjs イベントの this は何を表しますか? js での this の使用法の詳細な説明 (使用例付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。