ホームページ  >  記事  >  ウェブフロントエンド  >  「this」キーワードを理解する

「this」キーワードを理解する

PHPz
PHPzオリジナル
2023-08-30 17:05:09914ブラウズ

「this」キーワードを理解する

関数を作成すると、関数が実行されるオブジェクトにリンクされる this という名前のキーワードが (舞台裏で) 作成されます。つまり、this はその関数のスコープで使用できますが、関数がプロパティまたはメソッドであるオブジェクトへの参照です。

前の記事の cody オブジェクトを見てみましょう:

例:sample98.html

リーリー

getGender 関数内で、cody オブジェクト自体のドット表記 (cody.gender) を使用して gender## にアクセスする方法に注目してください。 # 属性。 thiscody オブジェクトを指しているため、cody オブジェクトには this オーバーライドを使用してアクセスできます。

例:sample99.html

リーリー

this.gender で使用される this は、関数が操作される cody オブジェクトを単に参照します。

this のトピックは混乱を招くかもしれませんが、そうではありません。一般に、this は、関数自体ではなく、関数に含まれるオブジェクトを参照するために関数内で使用されることに注意してください (例外として、new キーワードや の使用が含まれます) call()apply())。

キーワード

this は、変更できないことを除けば、他の変数と同じように見え、動作します。

arguments および関数に送信される引数とは対照的に、this は呼び出し/アクティブ化オブジェクト内のキーワード (プロパティではありません) です。


this の値はどのように決定されるのでしょうか?

すべての関数に渡される

this の値は、実行時に関数が呼び出されるコンテキストに基づきます。これは覚えておく必要がある癖の 1 つなので、注意してください。

次のコード例の

myObject オブジェクトには、sayFoo 関数を指す、sayFoo という名前のプロパティが割り当てられます。 sayFoo 関数がグローバル スコープから呼び出される場合、thiswindow オブジェクトを参照します。 myObject のメソッドとして呼び出された場合、thismyObject を参照します。

myObject

には foo という名前のプロパティがあるため、そのプロパティが使用されます。 例:sample100.html

リーリー

明らかに、

this

の値は、関数が呼び出されるコンテキストに基づいています。 myObject.sayFoosayFoo が両方とも同じ関数を指していると考えてください。ただし、sayFoo() が呼び出される場所 (コンテキスト) に応じて、this の値は異なります。 役立つ場合は、ヘッダー オブジェクトを明示的に使用した同じコードを示します (

window

)。 例:sample101.html

リーリー

関数を渡すとき、または関数への複数の参照を行うときは、関数を呼び出すコンテキストに応じて this の値が変化することに注意してください。

this

arguments を除くすべての変数は字句スコープに従います

this
キーワードは、ネストされた関数のヘッダー オブジェクトを参照します

this

が別の関数内に含まれる関数内で使用されるとどうなるのか疑問に思われるかもしれません。悪いニュースは、ECMA 3 では

this が失われ、関数が定義されているオブジェクトではなくヘッダー オブジェクト (ブラウザーの window オブジェクト) を参照していたことです。 以下のコードでは、func2

func3this が失われ、代わりに myObject ヘッダー オブジェクトを指します。 例:sample102.html リーリー

幸いなことに、この問題は ECMAScript 5 で解決される予定です。特に、関数を値として他の関数に渡し始めるときは、このジレンマに注意する必要があります。

次の例と、匿名関数を

foo.func1

に渡すと何が起こるかを考えてみましょう。匿名関数が

foo.func1 (関数内の関数) 内で呼び出される場合、匿名関数内の this 値は head オブジェクトへの参照になります。 例:sample103.html リーリー

これでもう忘れることはありません:

this

値は、そのホスト関数が別の関数内にラップされるか、別の関数のコンテキストで呼び出される場合、常に head オブジェクトへの参照になります (これも ECMAScript 5 で修正されました) ))。

スコープ チェーンを使用して入れ子関数の問題を解決する


this

値が失われないように、スコープ チェーンを使用して、親関数内で

this への参照を保持するだけです。次の例は、that という名前の変数を使用し、そのスコープを利用して関数コンテキストをより適切に追跡できる方法を示しています。 例:sample104.html

<!DOCTYPE html><html lang="en"><body><script>

var myObject = {
	myProperty: 'I can see the light', 
	myMethod : function(){
		var that = this; // Store a reference to this (myObject) in myMethod scope.
		var helperFunction = function() { // Child function.
			// Logs 'I can see the light' via scope chain because that = this.
			console.log(that.myProperty); // Logs 'I can see the light'.
			console.log(this); // Logs window object, if we don't use "that".
		}();
	}
}

myObject.myMethod(); // Invoke myMethod.

</script></body></html>


使用 call()apply() 控制 this 的值

this 的值通常由调用函数的上下文确定(除非使用 new 关键字,稍后会详细介绍),但您可以使用 this 的值>apply() 或 call() 来定义调用函数时 this 指向什么对象。使用这些方法就像在说:“嘿,调用 X 函数,但告诉该函数使用 Z 对象作为 this 的值。”通过这样做,JavaScript 确定 this 值的默认方式将被覆盖。

在下一个示例中,我们创建一个对象和一个函数。然后我们通过 call() 调用该函数,以便函数内 this 的值使用 myObject 作为其上下文。 myFunction 函数内的语句将使用属性填充 myObject,而不是填充头对象。我们更改了 this (在 myFunction 内部)引用的对象。

示例:sample105.html

<!DOCTYPE html><html lang="en"><body><script>

	var myObject = {};

	var myFunction = function (param1, param2) {
		// Set via call(), 'this' points to myObject when function is invoked.
		this.foo = param1;
		this.bar = param2;
		console.log(this) // Logs Object {foo = 'foo', bar = 'bar'}
	};

	myFunction.call(myObject, 'foo', 'bar'); // Invoke function, set this value to myObject.

	console.log(myObject) // Logs Object {foo = 'foo', bar = 'bar'}

</script></body></html>

在前面的示例中,我们使用了 call(),但也可以使用 apply()。两者之间的区别在于函数参数的传递方式。使用 call(),参数只是逗号分隔的值。使用 apply(),参数值在数组内部传递,如以下示例所示。

示例:sample106.html

<!DOCTYPE html><html lang="en"><body><script>

	var myObject = {};

	var myFunction = function (param1, param2) {
		// Set via apply(), this points to myObject when function is invoked.
		this.foo = param1;
		this.bar = param2;
		console.log(this) // Logs Object {foo = 'foo', bar = 'bar'}
	};

	myFunction.apply(myObject, ['foo', 'bar']); // Invoke function, set this value.

	console.log(myObject) // Logs Object {foo = 'foo', bar = 'bar'}

</script></body></html>

这里您需要学习的是,您可以覆盖 JavaScript 在函数作用域中确定 this 值的默认方式。


在用户定义的构造函数中使用 this 关键字

当使用 new 关键字调用函数时,构造函数中声明的 this 的值指的是实例本身。换句话说:在构造函数中,我们可以在实际创建对象之前通过 this 来利用该对象。在这种情况下, this 的默认值的更改方式类似于使用 call()apply()

在下面的示例中,我们设置了一个 Person 构造函数,该函数使用 this 来引用正在创建的对象。当创建 Person 的实例时,this.name 将引用新创建的对象,并在新对象中放置一个名为 name 的属性,并将参数 (name) 中的值传递给构造函数。 p>

示例:sample107.html

<!DOCTYPE html><html lang="en"><body><script>

	var Person = function (name) {
		this.name = name || 'john doe'; // this will refer to the instance created.
	}

	var cody = new Person('Cody Lindley'); // Create an instance based on the Person constructor.

	console.log(cody.name); // Logs 'Cody Lindley'.

</script></body></html>

同样,当使用 new 关键字调用构造函数时,this 指的是“将成为的对象”。如果我们没有使用 new 关键字,则 this 的值将是调用 Person 的上下文 - 在本例中为头对象。让我们看一下以下场景:

示例:sample108.html

<!DOCTYPE html><html lang="en"><body><script>

	var Person = function (name) {
		this.name = name || 'john doe';
	}

	var cody = Person('Cody Lindley'); // Notice we did not use 'new'.

	console.log(cody.name); // Undefined. The value is actually set at window.name

	console.log(window.name); // Logs 'Cody Lindley'.

</script></body></html>

原型方法中的关键字 this 引用构造函数实例

当在添加到构造函数 prototype 属性的函数中使用时,this 指的是调用该方法的实例。假设我们有一个自定义 Person() 构造函数。作为参数,它需要人的全名。如果我们需要访问人员的全名,我们将 whatIsMyFullName 方法添加到 Person.prototype 中,以便所有 Person 实例继承该方法。当使用 this 时,该方法可以引用调用它的实例(以及它的属性)。

这里我演示了创建两个Person对象(codylisa)以及继承的whatIsMyFullName方法,其中包含this关键字来访问实例。

示例:sample109.html

<!DOCTYPE html><html lang="en"><body><script>

	var Person = function (x) {
		if (x) { this.fullName = x };
	};

	Person.prototype.whatIsMyFullName = function () {
		return this.fullName; // 'this' refers to the instance created from Person()
	}

	var cody = new Person('cody lindley');
	var lisa = new Person('lisa lindley');

	// Call the inherited whatIsMyFullName method, which uses this to refer to the instance.
	console.log(cody.whatIsMyFullName(), lisa.whatIsMyFullName());

	/* The prototype chain is still in effect, so if the instance does not have a fullName property, it will look for it in the prototype chain. Next, we add a fullName property to both the Person prototype and the Object prototype. See the notes that follow this sample. */

	Object.prototype.fullName = 'John Doe';
	var john = new Person(); // No argument is passed so fullName is not added to the instance.
	console.log(john.whatIsMyFullName()); // Logs 'John Doe'.

</script></body></html>

结论

这里要带走的概念是 that 关键字 this 用于在 prototype 对象中包含的方法内部使用时引用实例。如果实例不包含该属性,则开始查找原型。

如果 this 指向的实例或对象不包含所引用的属性,则应用适用于任何属性查找的相同规则,并且将在原型链上“查找”该属性。因此,在我们的示例中,如果 fullName 属性未包含在我们的实例中,则将在 Person.prototype.fullName 中查找 fullName 属性,然后在 Object.prototype.fullName 中查找。

以上が「this」キーワードを理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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