通过简单的几个代码来带大家掌握this的绑定,翻越JavaScript中的大山!
this
JavaScript 中的 this
是一个特殊的关键字,它在函数内部指向函数当前所属的对象。this
的值在函数被调用时确定,而不是在函数被定义时确定。
this的绑定
默认绑定规则
1.默认绑定规则:当函数作为普通函数调用时,this
指向全局对象(在浏览器环境中通常是 window
对象)看如下代码:
function foo(){ //默认绑定规则
function bar(){
console.log(this) //此时this指向全局window
}
bar()
}
foo()
this是bar()函数中的,bar()的外层作用域是foo()函数体,我们说函数在哪个词法作用域中生效,this就指向哪里,要使bar()函数生效,所以得foo()函数生效,此时foo()函数的词法作用域为全局,所以this指向全局。
当内层有多个函数体包裹时,且为独立函数调用时this都指向window,因为this的查找就好似于原型链,不断的查找,直至this查到的对象为window。

隐式绑定规则
隐式绑定规则:当一个函数被对象所拥有且调用时,函数的this指向该对象。
function foo(){
console.log(this.a)
}
var obj = {
a:1,
foo:foo
}
obj.foo()
foo未带()表示引用,带了()表示调用,引用则表示foo()被obj所拥有,相当于foo:function foo(){ console.log(this.a)} 。
this在foo()函数中,但此时foo()被obj所拥有且被调用,所以此时this指向obj,输出的this.a=obj.a,a=1;
隐式丢失
隐式丢失:当函数被多个对象链式调用时,this指向引用函数的那个对象(就近原则)。
我们来看如下代码:此时this.a指向谁呢,输出的值又为多少呢?
//隐式丢失:当函数被多个对象链式调用时,this指向引用函数的那个对象
function foo(){
console.log(this.a)
}
var obj = {
a:1,
foo:foo
}
var obj2 = {
a:2,
obj:obj
}
obj2.obj.foo()
在obj中,foo引用了foo()函数,所以此时foo()为obj所拥有,又因为obj2中引用了obj变量,所以obj为obj2所拥有,于是当我们全局调用时 obj2.obj.foo(),结果this是指向obj呢还是obj2呢?

通过结果可以看出,输出的是obj中的a值,所以说this还是指向了obj而不是obj2,所以我们就称这种绑定为隐式丢失(指向就近的那个)。
显式绑定
在 JavaScript 中,你可以使用 call
、apply
和 bind
方法来显式地绑定函数内部的 this
值。这些方法允许你在调用函数时手动指定 this
的值,而不是依赖于函数的调用方式。
1.使用call方法
查看一段代码:
function foo(){
console.log(this.a);
}
var obj = {
a:1
}
foo.call(obj)
原本的this指向的是window(foo()独立调用时),此时使用call方法,使得this的绑定改绑到括号里面的obj当中,此时的输出为1。

function foo(x,y){
console.log(this.a,x+y);
}
var obj = {
a:1
}
foo.call(obj,4,5)

2.使用apply方法
apply的用法与call相似,但是apply接收参数的方法是数组的形式。
function foo(x,y){
console.log(this.a,x+y);
}
var obj = {
a:1
}
foo.apply(obj,[4,5]) //数组的形式[4,5]

3.使用bind方法
bind
方法创建一个新的函数,并将指定的 this
值绑定到新函数。不过,bind
方法不会立即调用原函数,而是返回一个新函数。该新函数的 this
值已经被绑定,但你可以稍后再调用它。
function greet() {
console.log("你好,我是" + this.name);
}
var obj = { name: "对象" };
var boundGreet = greet.bind(obj);
boundGreet(); // 输出:你好,我是对象

call、apply及bind三者的比较(显式绑定)
call
和apply
是直接调用函数并指定this
的值,而bind
是创建一个新函数。call
和apply
需要立即调用原函数,而bind
则可以延迟调用。call
和apply
的区别在于参数的传递方式,call
是参数列表,apply
是参数数组。
显式绑定 this
可以确保函数在任何上下文中都能得到正确的 this
值,从而提高代码的可靠性和可重用性。
new绑定
this指向实例对象(之前的文章中有细讲new)
箭头函数
var foo =()=>{
console.log(123);
}
foo() //与var foo =function(){} 相等

那么箭头函数和普通的函数有什么区别呢?我们通过代码来表示:
var obj ={
a:1
}
var foo =()=>{
console.log(this.a);
}
foo.call(obj)
var foo =function (){
console.log(this.a);
}
foo.call(obj)

此时的前者的运行结果为undefined,后者的运行结果为1,为什么呢?
是因为箭头函数中并没有this这一说,所以拿不到obj中的值,那么箭头函数中的this指向的是foo()函数外的window
例如:
var obj = {
a:1
}
function foo(){
var bar= ()=>{
console.log(this);
}
bar()
}
foo.call(obj)
箭头函数中没有this,所以this指向的是foo(),而foo.call(obj)使得this指向obj,所以可以输出a:1

转载自:https://juejin.cn/post/7366836510690197539