ホームページ > ウェブフロントエンド > jsチュートリアル > JavaScript での This の使用法に関するチュートリアルの例

JavaScript での This の使用法に関するチュートリアルの例

零下一度
リリース: 2017-06-25 09:38:12
オリジナル
1486 人が閲覧しました

「あなたの知らないJavaScript」という本を何度か読みました。読むたびに新しい発見があるようです。内容は一度では理解できないものもありますが、読むたびにいくつかの概念が理解できるようです。それを読んで。
this キーワードをもう一度読んでください。この概念は非常に柔軟ですが、理解するのが非常に難しいので、頻繁に読んでも損はないと思います。 JavaScriptが世の中に普及して学習コストが安くなるといいですね! this关键字。这个概念非常灵活,也非常难掌握,所以我觉得经常读读没有坏处。期待javascript一桶江湖,这样学习的成本就低啦!
参考本书的第二部分的第一章,第二章。

this关键字是js中最最复杂的机制之一。他被自动定义到所有函数的作用域中。

在学习这个关键字的过程中似乎也走了很长时间的弯路。你要问我为什么走了很长时间的弯路,关键的地方还是没有对核心的概念彻底学习和领会,这一点和小学生学习新知识没有任何区别。要想掌握this这个关键字,需要紧扣关键概念,不要凭空想象这到底是怎么一回事。

关键概念:js中的函数在调用的时候,一定,一定,一定会绑定在一个对象上,在分析this关键字的时候,一定要知道函数在调用的时候这个对象到底是谁?。
切记:js中函数的调用和定义是没有任何关系的,函数所绑定的对象直到他被调用的时候才能知道。

this关键字的不确定定是把双刃剑,一是函数调用时的对象不确定性,是js中函数的使用具有很大灵活性,每个对象都可以借用其他函数来完成功能。二是这也造成了this学习的一些困扰。所以在学习的时候先要理解this关键字的优点,然后再去学习造成困扰的地方

首先看看第一段代码
page 75

//注意只是定义了一个函数,并未调用,这时候函数是没有绑定任何对象function identify() {return this.name.toUpperCase();
}//同上面的函数,但是这个函数内部有点复杂,如果下面的代码看不懂//可以只看上面的函数function speak() {var greeting = "Hello, I'm " + identify.call( this );console.log( greeting );
}var me = { //定义了一个字面量对象
    name: "Kyle"
};var you = {//定义了一个字面量对象
    name: "Reader"
};//通过call方式把函数identify分别绑定到两个对象上//这时的this是指向me对象,和you对象
identify.call( me ); // KYLE  
identify.call( you ); // READER//通过call方式把函数call分别绑定到两个对象上//这时的this是指向me对象,和you对象
speak.call( me ); // Hello, I'm KYLE
speak.call( you ); // Hello, I'm READER
ログイン後にコピー

在javascript中定义函数的时候,函数是不属于任何对象的。这一点非常的关键,非常的关键,非常的关键。这是理解this关键字的第一个障碍。

this关键字在js函数定义的时候的不确定性使得js函数使用有极大的灵活性,任何对象都可以使用他。

this到底是什么?

this的绑定和函数定义的位置没有任何关系,只取决于函数调用的方式.
javascript中当一个函数被调用的时候,会创建一个活动记录(有时也称上下文)。这个记录包括函数在哪里被调用,函数的调用方法,传入的参数。this就是记录中的一个属性。

这样在学习javascript关键字的首要问题是要解决怎么知道到函数的调用位置.

js对象绑定规则

每个js函数在调用的时候一定要找到一个对象,绑定以后才能使用。 这里是理解了js函数的定义和调用的区别以后需要掌握的一个规模最庞大的概念,在js中一共有四种绑定方式.就我个人来看,绑定规则并不难,难点还是在js的函数作用域的理解. 尤其是默认绑定.这个绑定方式有极大的迷惑性。

默认绑定

这个是函数的独立调用,也就是在一个函数直接调用的时候,似乎是没有绑定到对象上的,但是根据前面的介绍,js中函数调用时必须要绑定到一个对象上。
看下面代码 page 83

  function foo() { //这是函数的定义位置console.log( this.a );
}  var a = 2;//这个变量定义的含义是什么呢?仅仅是赋值给a吗?

  foo(); // 2  //这是函数的调用位置。为什么会打印出2呢?
ログイン後にコピー

很多函数都是这么调用的,照猫画虎也可以写出来,但是理解了具体的含义就不一样了。
foo这个函数定义在全局作用域中(window作用域中),巧合的是他的调用也是在全局作用域中,注意这仅仅是巧合,巧合。 那么foo()调用的时候为什么会打印出变量 a的值呢?尽管使用了var这个关键字,但是分析作用域可以知道,a这个变量实际是全局变量,说的再明白一点,a实际是window这个全局对象的一个属性,2是这个属性的属性值。
foo()调用的时候是一丝不挂的全裸状态,仅仅是函数本身,没有任何修饰符,这个时候他也没有任何函数包裹,处在全局作用域下面,所以foo()里面的this是指向全局对象的,当要打印this.a的时候,寻找foo()调用位置会找到全局作用域,找全局作用域的属性this.a的时候会打印出2这个属性值。

我们在使用setTimeout,setInterval函数的时候,实际这两个函数就是一丝不挂的,同样绑定在window对象上。

隐式绑定

函数在调用的时候被添加了修饰符。看下面这个代码
page 85

  function foo() { //定义在全局作用下的函数,仅仅是定义,不是调用位置console.log( this.a );
}var obj = { //定义一个对象
    a: 2,foo: foo
};

obj.foo(); // 2  给foo()函数找了一个对象,this就指向这个对象了
ログイン後にコピー

这是最常见的方式了,如果不写前面的obj是不是就是上面的默认绑定了?

隐式丢失本書の第 2 部の第 1 章と第 2 章を参照してください。

このキーワードは、js で最も複雑なメカニズムの 1 つです。すべての関数のスコープ内で自動的に定義されます。

私もこのキーワードを学ぶ過程で、かなり遠回りしたような気がします。なぜ遠回りをしたのかというと、重要なのは、私がまだ核となる概念を完全に学習して理解していないということです。これは、新しい知識を学ぶ小学生と何ら変わりません。 this というキーワードをマスターしたい場合は、重要な概念に固執し、これが一体何なのかを想像する必要はありません。 🎜🎜重要な概念: js の関数が呼び出されるとき、その関数は必ずオブジェクトにバインドされます。 this キーワードを分析するとき、関数が呼び出されたときのオブジェクトが誰であるかを知る必要があります。 。 🎜覚えておいてください: 呼び出しと js の関数の定義の間には関係がありません。関数にバインドされたオブジェクトは、呼び出されるまでわかりません。 🎜🎜このキーワードの不確実性は諸刃の剣です。1 つは、関数が呼び出されるときのオブジェクトの不確実性です。js での関数の使用には、その機能を完了するために他の関数を借用することができます。第二に、これはこれを学習する際にもいくつかの問題を引き起こしました。したがって、学習するときは、まずこのキーワードの利点を理解してから、問題の原因となる場所に進む必要があります🎜🎜まず最初のコード部分を見てください🎜75ページ🎜
   var  that=this; //这是什么含义
ログイン後にコピー
🎜JavaScriptで関数を定義するとき、 function はどのオブジェクトにも属しません。これは非常に重要、非常に重要、非常に重要です。これがこのキーワードを理解するための最初の障害です。 🎜
🎜 js 関数を定義するときのこのキーワードの不確実性により、js 関数の使用が非常に柔軟になり、どのオブジェクトでも使用できます。 🎜

これは一体何ですか?

🎜このバインディングは関数定義の場所とは関係がありません。関数の呼び出し方法にのみ依存します。🎜 JavaScript で関数が呼び出されると、アクティビティ レコードが作成されます。作成されます (コンテキストとも呼ばれることもあります)。このレコードには、関数が呼び出された場所、関数の呼び出しメソッド、および渡されたパラメーターが含まれます。これはレコード内の属性です。 🎜🎜JavaScript キーワードを学習するときの最初の 問題は、関数の呼び出し場所を知る方法です。🎜

js オブジェクト バインディング ルール

🎜各 js 関数が呼び出される場所を見つける必要があります。この時点でオブジェクトを作成し、使用する前に bind を実行します。 これは、js 関数の定義と呼び出しの違いを理解した上で習得する必要がある最大の概念です。js には 4 つのバインディング メソッドがあります。個人的には、バインド ルールは難しくありません。<コード> 関数のスコープを理解することが難しいです。 js の特に default binding は非常にわかりにくいです。 🎜

デフォルト バインディング

🎜これは関数の独立した呼び出しです。つまり、関数が直接呼び出された場合、その関数はオブジェクトにバインドされないようです。関数は js で呼び出されます。オブジェクトにバインドする必要があります。 🎜ページ 83 の下のコードを見てください🎜
function foo() { //定义了一个函数console.log( this.a );
}var obj = { //定义了一个对象字面量
    a: 2,foo: foo  //函数作为对对象的属性
};var bar = obj.foo; //把obj对象的函数foo属性赋值给bar变量//这里就是理解这个问题的关键,如果你现在认为调用bar()的时候绑定的对象//是obj那就完全搞错了。这个时候仅仅是把函数foo赋值给了var变量,//并没有把对象也给bar变量,因为这里还不是foo()函数的调用位置,现在//foo函数还没有绑定对象,那么调用bar()的时候对象到底是谁?不知道。//调用的时候才知道。var a = "oops, global"; // 任然是全局对象的属性
bar(); // "oops, global" 这里执行的是默认绑定,this就是去全局对象啦
ログイン後にコピー
ログイン後にコピー
🎜多くの関数がこの方法で呼び出されます。猫と虎のように書くこともできますが、具体的な意味を理解すると異なります。 🎜関数 foo はグローバル スコープ (ウィンドウ スコープ) で定義されていますが、これは単なる偶然であることに注意してください。 では、なぜ foo() が呼び出されたときに変数 a の値が出力されるのでしょうか?キーワード var が使用されていますが、スコープ分析から変数 a が実際にはグローバル変数であることがわかります。より明確に言うと、a は実際にはグローバル オブジェクト ウィンドウの属性であり、2 はこの属性の属性値です。 。 🎜 foo() が呼び出されるとき、それは修飾子のない単なる関数そのものです。この時点では、関数ラッパーはなく、グローバル スコープの下にあるため、foo() の this は、はい、this.a を出力したい場合は、foo() の呼び出し位置を探すと、グローバル スコープの属性 this.a が出力されます。属性値 2。 🎜
🎜 setTimeout 関数と setInterval 関数を使用する場合、これら 2 つの関数は実際には裸であり、ウィンドウ オブジェクトにもバインドされます。 🎜

暗黙的バインディング

🎜 関数が呼び出されるときに、修飾子が関数に追加されます。以下のコードを見てください🎜85ページ🎜
function foo() { //定义一个函数console.log( this.a );
}function doFoo(fn) { //fn是形参// 如果函数作为实参传入相当于代码 var fn=obj.foo//和上面一段代码是完全一样的,只是函数本身,并没有绑定任何对象

    fn(); // 在这里调用的时候,由于fn只代表foo()函数,被绑定到全局对象上了
}var obj = {a: 2,foo: foo
};var a = "oops, global"; // `a` also property on global object

doFoo( obj.foo ); // "oops, global"不要被obj.foo迷惑了//没有实际执行函数的调用,此时obj.foo仅仅代表没有绑定任何对象的函数//这个代码块看着眼熟么?这就是javascript中回调函数的样子,当//一个函数作为参数传递进另一个函数的时候,这个参数函数就找不到自己绑定的对象是谁了,//所以就默认绑定到全局对象上了。但是我们既然在一个函数里调用另一个函数,肯定是要用这个函数操作当前的对象,那么既然找不到了,我们就手动给他指定一个对象吧。这就是为什么要使用//var  that=this的原因。我觉得理解这个概念,js的功力至少会增加5%
ログイン後にコピー
ログイン後にコピー
🎜これが最も一般的な方法です。前のobjを書かない場合、それは上記のデフォルトのバインディングになります。 🎜🎜Implicit loss🎜JSコードのネストされたコールバック関数で、外側の関数の先頭にある文をよく見かけます🎜rrreee🎜すでに使い方はご存知かもしれませんが、もっと便利になります意味がわかればとても便利です🎜

看下面段代码.这段代码其实以前我也不太理解,问题还是没有彻底领悟js函数定义和调用之间是没有关系的这一点。
page 86

function foo() { //定义了一个函数console.log( this.a );
}var obj = { //定义了一个对象字面量
    a: 2,foo: foo  //函数作为对对象的属性
};var bar = obj.foo; //把obj对象的函数foo属性赋值给bar变量//这里就是理解这个问题的关键,如果你现在认为调用bar()的时候绑定的对象//是obj那就完全搞错了。这个时候仅仅是把函数foo赋值给了var变量,//并没有把对象也给bar变量,因为这里还不是foo()函数的调用位置,现在//foo函数还没有绑定对象,那么调用bar()的时候对象到底是谁?不知道。//调用的时候才知道。var a = "oops, global"; // 任然是全局对象的属性
bar(); // "oops, global" 这里执行的是默认绑定,this就是去全局对象啦
ログイン後にコピー
ログイン後にコピー

下面这段代码就是使用var that=this的场景
在使用回调函数的时候要留心。js中函数是一等对象,可以作为另一个函数的参数传入函数。 问题就出在这里了,函数一旦作为实参代替形参的时候,实际也执行了和上面代码一样的赋值过程,实际只是传递了函数本身,原先的对象就没有了。

page 86

function foo() { //定义一个函数console.log( this.a );
}function doFoo(fn) { //fn是形参// 如果函数作为实参传入相当于代码 var fn=obj.foo//和上面一段代码是完全一样的,只是函数本身,并没有绑定任何对象

    fn(); // 在这里调用的时候,由于fn只代表foo()函数,被绑定到全局对象上了
}var obj = {a: 2,foo: foo
};var a = "oops, global"; // `a` also property on global object

doFoo( obj.foo ); // "oops, global"不要被obj.foo迷惑了//没有实际执行函数的调用,此时obj.foo仅仅代表没有绑定任何对象的函数//这个代码块看着眼熟么?这就是javascript中回调函数的样子,当//一个函数作为参数传递进另一个函数的时候,这个参数函数就找不到自己绑定的对象是谁了,//所以就默认绑定到全局对象上了。但是我们既然在一个函数里调用另一个函数,肯定是要用这个函数操作当前的对象,那么既然找不到了,我们就手动给他指定一个对象吧。这就是为什么要使用//var  that=this的原因。我觉得理解这个概念,js的功力至少会增加5%
ログイン後にコピー
ログイン後にコピー

以上がJavaScript での This の使用法に関するチュートリアルの例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート