この記事ではJavaScriptにおけるこれに起因するバグの解析とそれに関連する処理方法の解析を中心に紹介しますので一緒に勉強していきましょう。
js では、このコンテキストは常に予測不可能です。実際、さまざまな状況での実行方法を理解するだけで済みます。あなた:
JavaScript でよく使われる非常に特殊なもので、初心者がよく悩むのが「これ」です。このクラスでは、この「これ」について話します。
これは通常、オブジェクトを指しますが、状況に応じて異なるオブジェクトを指します。 「これ」をより深く理解するために、いくつかの異なるシナリオを見てみましょう。
window オブジェクト (グローバル オブジェクト)
ここでは、「this」を 3 つの異なる状況で出力します。つまり、関数の最も外側の環境で直接実行します。関数式を使用して実行します。関数文と関数式の違いについては、注1)を参照してください。
これら 3 つの「this」は、グローバル環境のウィンドウ オブジェクト (グローバル オブジェクト) である同じオブジェクトを指すことがわかります:
これは、この関数を直接使用できることを意味し、これにより、ウィンドウ オブジェクトに新しい属性が作成されます。
ここでは、 this.NewVariable = "..."
を使用して、ウィンドウ オブジェクトに新しい属性を作成します。ここで this.NewVariable または window.NewVariable を入力する必要がない理由は、「.」を使用せずにグローバル オブジェクト (ウィンドウ) 内の任意の属性を直接使用できるためです。 this.NewVariable = "..."
来在window object建立新的属性,函数的最后,我们则可以直接console.log(NewVariable),这里之所以可以不用打this.NewVariable或window.NewVariable是因为任何在global object (window)的属性,我们都可以直接去使用它,而不用使用”.”。
跑出来的结果会像这样子:
它会打印出我们的”Create a new property”,同时,在window这个大的object中,我们也会找到NewVariable这个属性:
method in object
我们知道,在对象里的值如果是原生值(primitive type;例如,字串、数值、逻辑值),我们会把这个新建立的东西称为「属性(property)」;如果对象里面的值是函数(function)的话,我们则会把这个新建立的东西称为「方法(method)」。
在这里,我们就要来建立method:
首先,我们利用object literal的方式创建一个对象c,里面包含属性name和方法log。log是一个匿名函数(anonymous function),函数内容很简单,就是打印this而已(关于匿名函数可参考注1)。最后则是使用c.log的方式来执行该方法。
让我们来看看,这时候的”this”会是什么呢?
答案是对象c!
当这个函数是对象里面的method时,这时候的this就会指向到包含这个method的对象
JavaScript中关于this的一个bug
让我们更进一步延伸来看这个范例:
假设我们在method log裡面多这一行this.name = "Updated Object C name"
因为我们知道”this”现在指的是对象c,所以可以想像的,当我执行这个method的时候,它会去变更c.name的值。
这个部分是没有什么大问题的,不过让我们继续看下去……。
假设我在method log裡面在做一些变更,我在这个method裡面,另外建立一个函数叫做setname,一样是用this.name = newname
🎜「新しいプロパティの作成」が出力されます。同時に、ラージ オブジェクト ウィンドウで、プロパティ NewVariable も見つかります: 🎜🎜🎜🎜オブジェクトのメソッド🎜🎜オブジェクトの値がプリミティブ値 (プリミティブ型。文字列、数値、論理値など) の場合、この新しいメソッドを追加することがわかっています。 value 作成されたものを「プロパティ」と呼びます。オブジェクト内の値が関数の場合、新しく作成されたものを「メソッド」と呼びます。 🎜🎜ここでは、メソッドを確立します: 🎜🎜まず、オブジェクト リテラルを使用して、属性名とメソッド ログを含むオブジェクト c を作成します。 Log は匿名関数です。関数の内容はこれを出力するだけです (匿名関数については注 1 を参照)。最後に、c.log を使用してこのメソッドを実行します。 🎜🎜🎜🎜今回は見てみましょう「これ」とは何でしょうか? 🎜🎜答えはオブジェクト c です! 🎜🎜この関数がオブジェクト内のメソッドである場合、これはこのメソッドを含むオブジェクトを指します🎜🎜🎜🎜JavaScript のこれに関するバグ🎜🎜この例をさらに拡張してみましょう: 🎜🎜この行
this をメソッド ログ .name = "更新されたオブジェクト C 名" に追加するとします。 "
🎜🎜🎜🎜それは私たちが知っているからです「this」はオブジェクト c を参照するようになりました。このメソッドを実行すると、c.name の値が変更されることが想像できます。 🎜🎜🎜🎜この部分は大きな問題はありません。でも、探し続けましょう…。 🎜🎜このメソッドでは、setname という別の関数を作成して、オブジェクト c の名前を変更するとします。属性。 🎜🎜次に、setname 関数を実行して、オブジェクト c の name の属性値を「オブジェクト c の新しい名前」に変更し、最後に「this」を出力して確認します。 🎜🎜🎜🎜その結果、オブジェクト c の name 属性の値が「オブジェクト c の新しい名前」に変更されていないことがわかりますが、依然として同じです。 ?どうしてこうなりました?
注意深く見て、ウィンドウ オブジェクトに戻って見てみましょう。ウィンドウ オブジェクト内に新しい属性「name」が見つかり、その値が「オブジェクト c の新しい名前」であることがわかります。
これはどういう意味ですか?これは、関数 setname で指定した this が、オブジェクト C ではなく、グローバル オブジェクト (ウィンドウ オブジェクト) を指していることを意味します。
setname 関数では、console.log(this) を使用して確認します。
log メソッドでは、console.log(this) を合計 3 回実行し、結果は次のようになります。
setname の最初と 3 番目の "this" はオブジェクト c を指しますが、setname の 2 番目の this はウィンドウ オブジェクト (グローバル オブジェクト) を指します。これが、setname 関数が名前の名前を変更できない理由です。 「this」はオブジェクト c をまったく指していないため、オブジェクト c の属性。
そして多くの人は、これは JavaScript のバグだと考えています。
それでは何ができるでしょうか
それでは、上記の例に遭遇したとき、異なるオブジェクトを指すことを避けるために何ができるでしょうか?
多くの人の解決策は次のようになります。オブジェクトがすべて参照されることがわかっているので、これを行うことができます
ステップ 1
関数全体の先頭に行を追加します var self = this
(有些人会用var that = this
)。参照の特性により、self と this は同じオブジェクトを指し、this はオブジェクト c を指すため、self もオブジェクト c を指します。
ステップ 2
次に、メソッド ログで最初に使用されていた「this」を「self」に変更します。これにより、上記の例のように間違ったオブジェクトを指すことを心配することなく、self が c オブジェクトを指すようになります。
結果は予想どおりで、console.log(self) が 2 回目に使用されると、オブジェクト c の name 属性の値が再度置き換えられます。
概要
要約しましょう:
グローバル環境で関数を作成してこれを出力すると、これはグローバル オブジェクト、つまりウィンドウ オブジェクトを指すことになります。
オブジェクト内に関数、つまりメソッドを作成する場合、これは通常、そのメソッドを含むオブジェクトを指します(「通常」と言う理由は、上記の外部のバグ状況を除くためです)。
メソッド内で this が何を指しているのかわからない状況に遭遇した場合、不要なエラーを避けるために、メソッドの先頭に変数を作成し、 this (var self = this) として指定できます。
4. この状況でこれが何を指すのかまだわからない場合は、console.log を見て見てください。
サンプルコード
// function statement function a(){ console.log(this); this.NewVariable = "Create a new property"; } a(); console.log(NewVariable); var c = { name:"The C object", log: function(){ var self = this; self.name = "Updated object C name"; console.log(self); var setname = function(newname){ self.name = newname; console.log(self); } setname("New name for object c"); console.log(self) } } c.log();
上記は私が皆さんのためにまとめたもので、将来皆さんのお役に立てれば幸いです。
関連記事:
vue-cliを使用してマルチページアプリケーションを実装する方法
Vueプロジェクト最適化のニーズ 何に注意すべきでしょうか?
以上がJS でこれによって引き起こされるバグの詳細な解釈の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。