this
のポイント 実際、ES5 では、this のポイントは常に同じ原則に従っています。つまり、this は常にそれを最後に呼び出したオブジェクトを指します。さあ、フォローして 3 回読んでください。これは常に を指します。最後に呼び出したオブジェクト これは常に、最後に呼び出したオブジェクトを指します。 これは、最後に呼び出したオブジェクトを指します。この文を覚えておいてください。半分はすでに知っています。
これも典型的な面接の質問です。JS の This、apply、call、bind は典型的な面接の質問です。this と call、apply、bind の違いを理解するのが最善です。 Script House の編集者に従って、この知識を学び、適用、呼び出し、バインドしてみましょう。
最も単純な例を見てみましょう:
例 1:
var name = "windowsName"; function a() { var name = "Cherry"; console.log(this.name); // windowsName console.log("inner:" + this); // inner: Window } a(); console.log("outer:" + this) // outer: Window
ログが windowsName である理由は誰もが知っていると思います。なぜなら、今の文によると、「これは常に最後に呼び出したオブジェクトを指している」からです。 a が a(); と呼ばれる最後の場所を見てみましょう。前に呼び出されなかったオブジェクトは、window.a(); と同等です。ここでは strict モードを使用していないことに注意してください。モードが使用されている場合、グローバル オブジェクトが未定義である場合、エラー「Uncaught TypeError: Cannot read property 'name' of unknown」が報告されます。
この例をもう一度見てください:
例 2:
var name = "windowsName"; var a = { name: "Cherry", fn : function () { console.log(this.name); // Cherry } } a.fn();
この例では、関数 fn がオブジェクト a によって呼び出されるため、出力される値は a の name の値です。もう少し分かりやすくなりましたか~
少し変更を加えてみましょう:
例 3:
var name = "windowsName"; var a = { name: "Cherry", fn : function () { console.log(this.name); // Cherry } } window.a.fn();
ここで Cherry が表示されている理由も、先ほどの文「これは常に最後に呼び出したオブジェクトを指します」のためです。最後に、それを呼び出すオブジェクトは依然としてオブジェクト a です。
この例をもう一度見てみましょう:
例 4:
var name = "windowsName"; var a = { // name: "Cherry", fn : function () { console.log(this.name); // undefined } } window.a.fn();
なぜここに undefine が出力されるのでしょうか?これは、先ほど説明したように、 fn がオブジェクト a によって呼び出されるためです。これは、 fn の内部 this がオブジェクト a であり、 name がオブジェクト a で定義されていないため、ログ内の this.name の値が undefine であるためです。
この例は、さらに次のことを示しています。 fn を最後に呼び出したオブジェクトは a であるため、 this は常にそれを最後に呼び出したオブジェクトを指します。そのため、a に name 属性がない場合でも、次の this.name の検索は続行されません。前のオブジェクトですが、未定義を直接出力します。
もっと分かりにくい例を見てみましょう:
例 5:
var name = "windowsName"; var a = { name : null, // name: "Cherry", fn : function () { console.log(this.name); // windowsName } } var f = a.fn; f();
ここで疑問があるかもしれませんが、なぜチェリーではないのでしょうか? これは、オブジェクトの fn メソッドが変数 f に割り当てられているにもかかわらず、次に、この文を読んでください: 「これは常に、最後に呼び出したオブジェクトを指します。」 f が呼び出されなかったので、結局 fn() はウィンドウによって呼び出されています。したがって、これはウィンドウを指します。
上記の 5 つの例から、es5 では、this のポイントは常に最後に呼び出したオブジェクトを指すことがわかります。
別の例を見てみましょう:
例 6:
var name = "windowsName"; function fn() { var name = 'Cherry'; innerFunction(); function innerFunction() { console.log(this.name); // windowsName } } fn()
今読んだら、なぜこれが起こっているのか理解できるはずです(o゚▽゚)o。
thisの点を変更する方法
thisの点を変更する以下の方法をまとめました
ES6のarrow関数を使う
関数内で_this = thisを使う
apply、call、bindを使う
新しいインスタンス オブジェクトを変換します
例 7:
var name = "windowsName"; var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() },100); } }; a.func2() // this.func1 is not a function
アロー関数を使用しない場合、setTimeout を呼び出す最後のオブジェクトは window ですが、window には func1 関数がないため、エラーが報告されます。
このポインタを変更するこのセクションでは、デモとしてこの例を変換します。
アロー関数
ご存知のとおり、ES6 のアロー関数は、ES5 でこれを使用する場合の落とし穴を回避できます。アロー関数の this は、関数が実行されるときではなく、関数が定義されるときに常に this を指します。アロー関数は次の文を覚えておく必要があります。「アロー関数には this バインディングがありません。その値はスコープ チェーンを検索して決定する必要があります。アロー関数がアロー関数以外の関数に含まれている場合、このバインディングは次のようになります。」最も近い非矢印関数は this、それ以外の場合は未定義です。」
例 8:
var name = "windowsName"; var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( () => { this.func1() },100); } }; a.func2() // Cherry
関数内で _this = this を使用する
ES6 を使用しない場合は、このメソッドが最も簡単でエラーのない方法になるはずです。まず、この関数を呼び出すオブジェクトを変数 _this に保存します。 _this が変更されないように、関数内で this _this を使用します。
例 9:
var name = "windowsName"; var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { var _this = this; setTimeout( function() { _this.func1() },100); } }; a.func2() // Cherry
この例では、func2 で最初に var _this = this; を設定します (this は func2 を呼び出すオブジェクト a)。これは、func2 の setTimeout がウィンドウによって呼び出されないようにするためです。窓。 this (変数 a を指す) を変数 _this に代入し、func2 で _this を使用するときにオブジェクト a を指すようにします。
apply、call、bind を使用します
apply、call、bind 関数を使用すると、この方向を変更することもできます。原理については後で説明します。まず、その実装方法を見てみましょう。 10:
var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() }.apply(a),100); } }; a.func2() // Cherry
callの使用
例11:
var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() }.call(a),100); } }; a.func2() // Cherry
bindの使用
例12:
var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() }.bind(a)(),100); } }; a.func2() // Cherry
apply、call、bindの違い
刚刚我们已经介绍了 apply、call、bind 都是可以改变 this 的指向的,但是这三个函数稍有不同。
在 MDN 中定义 apply 如下;
apply() 方法调用一个函数, 其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数
语法:
fun.apply(thisArg, [argsArray])
thisArg:在 fun 函数运行时指定的 this 值。需要注意的是,指定的 this 值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。
argsArray:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。浏览器兼容性请参阅本文底部内容。
apply 和 call 的区别
其实 apply 和 call 基本类似,他们的区别只是传入的参数不同。
call 的语法为:
fun.call(thisArg[, arg1[, arg2[, ...]]])
所以 apply 和 call 的区别是 call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组。
例 13:
var a ={ name : "Cherry", fn : function (a,b) { console.log( a + b) } } var b = a.fn; b.apply(a,[1,2]) // 3
例 14:
var a ={ name : "Cherry", fn : function (a,b) { console.log( a + b) } } var b = a.fn; b.call(a,1,2) // 3
bind 和 apply、call 区别
我们先来将刚刚的例子使用 bind 试一下
var a ={ name : "Cherry", fn : function (a,b) { console.log( a + b) } } var b = a.fn; b.bind(a,1,2)
我们会发现并没有输出,这是为什么呢,我们来看一下 MDN 上的文档说明:
bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。
所以我们可以看出,bind 是创建一个新的函数,我们必须要手动去调用:
var a ={ name : "Cherry", fn : function (a,b) { console.log( a + b) } } var b = a.fn; b.bind(a,1,2)() // 3
相关推荐:
以上がこの例の共有、JS での適用、呼び出し、バインドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。