ホームページ  >  記事  >  ウェブフロントエンド  >  これは JS でバグ分析をトリガーします

これは JS でバグ分析をトリガーします

小云云
小云云オリジナル
2017-12-13 09:22:091253ブラウズ

js では、このコンテキストは常に予測不可能であり、実際には、さまざまな状況での実行方法を理解するだけで済みます。 JavaScript での処理方法の分析と同様に、皆様のお役に立てれば幸いです。

JavaScriptには非常に特殊でよく使われる、初心者を悩ませることが多い「これ」があります。このクラスでは、この「これ」について話します。

これは通常、オブジェクトを指しますが、状況に応じて異なるオブジェクトを指します。 「これ」をより深く理解するために、いくつかの異なるシナリオを見てみましょう。

window オブジェクト (グローバル オブジェクト)

ここでは、「this」を 3 つの異なる状況で出力します。つまり、関数の最も外側の環境で直接実行します。関数式を使用して実行します。関数文と関数式の違いについては、注1)を参照してください。


これら 3 つの「this」は、グローバル環境のウィンドウ オブジェクト (グローバル オブジェクト) である同じオブジェクトを指すことがわかります。この関数を使用すると、ウィンドウ オブジェクトに新しいプロパティが作成されます。

ここでは、 this.NewVariable = "..." を使用して、関数の最後に新しいプロパティを作成します。 console.log(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

「新規作成」が出力されます。 property" と同時に、ラージ オブジェクト ウィンドウで NewVariable 属性も見つかります:


🎜オブジェクト内のメソッド🎜🎜オブジェクト内の値がプリミティブ値 (プリミティブ型。文字列、数値、論理値など) である場合、次のようになります。この新しく作成されたものを「プロパティ」と呼びます。オブジェクト内の値が関数の場合、この新しく作成されたものを「メソッド」と呼びます。 🎜🎜ここでは、メソッドを確立します: 🎜🎜まず、オブジェクト リテラルを使用して、属性名とメソッド ログを含むオブジェクト c を作成します。 Log は匿名関数です。関数の内容はこれを出力するだけです (匿名関数については注 1 を参照)。最後に、c.log を使用してこのメ​​ソッドを実行します。 🎜🎜🎜🎜🎜今回はこちらを見てみましょう「これ」は何になるでしょうか? 🎜🎜答えはオブジェクト c です! 🎜🎜この関数がオブジェクト内のメソッドである場合、これはこのメソッドを含むオブジェクトを指します🎜🎜🎜🎜🎜JavaScript のこれに関するバグ🎜🎜この例をさらに拡張してみましょう: 🎜🎜メソッド ログに次の行を追加するとします。 this.name = "Updated Object C name"🎜🎜🎜🎜🎜 「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 は window オブジェクト (グローバル オブジェクト) を指します。これが、setname 関数がオブジェクト c の name 属性の名前。「this」はオブジェクト 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 (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();

この記事を読んだ後、これが原因で JS に発生するバグに誰もが気づいたと思います。必要な場合は、すぐに収集してください。

関連する推奨事項:

jsのthisを理解する

JSのthisとeventの違いの詳細な説明

js_javascriptスキルでのthisの使用例分析

以上がこれは JS でバグ分析をトリガーしますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。