Home > Article > Web Front-end > Sharing examples of this, apply, call and bind in JS
The pointing of this
In ES5, in fact, the pointing of this always adheres to the same principle: this always points to the last object that called it. Come on, follow me and read it three times: this always points to the last object that called it. That object, this always points to the last object that called it, this always points to the last object that called it. Remember this sentence, you already know half of this.
This is another classic interview question. This, apply, call, and bind in JS are a classic interview question. It is best to understand the difference between the direction of this and call, apply, and bind. Let's follow the editor of Script House to learn the knowledge of this, apply, call, and bind.
Let’s take a look at the simplest example:
Example 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
I believe everyone knows why the log is windowsName, because according to the sentence just now "This always points to the object that last called it." Let's look at the last place where a was called a();. The object that was not called before is the global object window, which is equivalent to window.a(); note that we don't have Use strict mode. If strict mode is used, the global object is undefined, and the error Uncaught TypeError: Cannot read property 'name' of undefined will be reported.
Look at this example again:
Example 2:
var name = "windowsName"; var a = { name: "Cherry", fn : function () { console.log(this.name); // Cherry } } a.fn();
In this example, function fn is called by object a, so the printed value is the name in a value. Is it a little clearer~
Let’s make a small change:
Example 3:
var name = "windowsName"; var a = { name: "Cherry", fn : function () { console.log(this.name); // Cherry } } window.a.fn();
The reason why Cherry is printed here is also because of the sentence just now " "this always points to the object that last called it", and the last object that called it is still object a.
Let’s take a look at this example again:
Example 4:
var name = "windowsName"; var a = { // name: "Cherry", fn : function () { console.log(this.name); // undefined } } window.a.fn();
Why is undefined printed here? This is because, as just described, fn is called by object a, which means that the internal this of fn is object a, and name is not defined in object a, so the value of this.name in log is undefined. .
This example still illustrates: this always points to the object that last called it, because the object that last called fn was a, so even if there is no name attribute in a, it will not continue to search for this from the previous object. name, but directly output undefined.
Let’s look at a more confusing example:
Example 5:
var name = "windowsName"; var a = { name : null, // name: "Cherry", fn : function () { console.log(this.name); // windowsName } } var f = a.fn; f();
You may have questions here, why is it not Cherry? This is because although the fn of an object is The method is assigned to variable f, but it is not called. Then read this sentence to me: "this always points to the object that last called it." Since f was not called just now, fn() is still called by window in the end. of. So this points to window.
We can see from the above five examples that the point of this cannot be determined when it is created. In es5, this always points to the object that last called it.
Let’s look at another example:
Example 6:
var name = "windowsName"; function fn() { var name = 'Cherry'; innerFunction(); function innerFunction() { console.log(this.name); // windowsName } } fn()
You should be able to understand why this is happening after reading it now (o゚▽゚)o.
How to change the point of this
I summarized the following methods to change the point of this:
Use ES6 arrow function
Use it inside the function _this = this
Use apply, call, bind
new to instantiate an object
Example 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
without using arrow functions Next, an error will be reported because the last object to call setTimeout is window, but there is no func1 function in window.
We will transform this example as a demo in this section of changing this pointer.
Arrow Function
As we all know, ES6’s arrow function can avoid the pitfalls of using this in ES5. The this of an arrow function always points to this when the function is defined, not when it is executed. , the arrow function needs to remember this sentence: "There is no this binding in the arrow function, and its value must be determined by looking up the scope chain. If the arrow function is included by a non-arrow function, this binding is the nearest non-arrow function. function's this, otherwise, this is undefined".
Example 8:
var name = "windowsName"; var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( () => { this.func1() },100); } }; a.func2() // Cherry
Use _this = this inside the function
If you do not use ES6, then this method should be the simplest and error-free method , we first save the object that calls this function in the variable _this, and then use this _this in the function, so that _this will not change.
Example 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
In this example, in func2, first set var _this = this;, where this is the object a that calls func2, in order to prevent the setTimeout in func2 from being This in setTimeout caused by the window call is window. We assign this (pointing to variable a) to a variable _this, so that when we use _this in func2, it points to object a.
Use apply, call, bind
Using the apply, call, and bind functions can also change the direction of this. The principle will be discussed later. Let’s first take a look at how it is implemented:
Use apply
Example 10:
var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() }.apply(a),100); } }; a.func2() // Cherry
Use call
Example 11:
var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() }.call(a),100); } }; a.func2() // Cherry
Use bind
Example 12:
var a = { name : "Cherry", func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() }.bind(a)(),100); } }; a.func2() // Cherry
Differences between apply, call and 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
相关推荐:
The above is the detailed content of Sharing examples of this, apply, call and bind in JS. For more information, please follow other related articles on the PHP Chinese website!