的绑定规则对于JavaScript新手来说,这是一个非常基础和难懂的知识点。例如,在下面的代码中,有3种方法可以指向this。functionfoo(){console.log(this.a);}vara=1;varobj={a:2,foo:foo};foo();//1obj.foo();//2foo.call({a:3});//3在《你不知道的 JavaScript》这本书中,我终于更清楚地理解了这一点。这是函数运行的环境对象,它指向运行时的位置,而不是定义的位置。根据这个绑定规则,分为以下四种:默认绑定隐式绑定显式绑定newbinding1.默认绑定默认情况下,this指向全局对象。例如下面的代码。vara=2;console.log(this.a);//2//函数中functionfoo(){console.log(this.a);}foo();//2//回调函数中functiondoFoo(){returnfunction(){console.log(this.a);};}doFoo()();//2但是在函数的严格模式下,this不能指向全局对象,所以this会被绑定未定义。functionfoo(){"usestrict";console.log(this);}foo();//undefined2.隐式绑定当函数作为方法调用时,需要考虑运行时上下文。functionfoo(){console.log(this.a);}varobj={a:2,foo:foo};obj.foo();//在2的代码中,在foo(),所以obj对象是函数的上下文。this将绑定到该对象。此外,还需要注意以下三种情况。它们会导致绑定对象丢失,从而将this绑定到全局对象或undefined。Case1这段代码中,obj.foo()和bar()虽然都指向同一个函数,但是执行结果却不同。可以理解bar()是一个没有任何修饰的函数调用,相当于直接调用foo(),所以应用默认绑定。functionfoo(){console.log(this.a);}vara=3;varobj={a:2,foo:foo};varbar=obj.foo;obj.foo();//2bar();//3情况2还有一种情况发生在回调函数中。原理同上。修改上面的代码,将obj.foo作为参数传递给doFoo()函数,实际上指的是foo()函数本身,所以采用默认绑定。functionfoo(){console.log(this.a);}vara=3;varobj={a:2,foo:foo};functiondoFoo(fn){returnfn();}doFoo(obj.foo);//3案例三在一些流行的JavaScript库中,在进行事件处理操作时,回调函数的this可能会被强行绑定到DOM元素上。这种情况也值得注意。3.显式绑定JavaScript提供了call()、apply()和bind()方法,可以强制绑定函数的this对象。functionfn(){console.log(this.a);}fn.call({a:3});//3通过fn.call(obj),我们在函数运行时强制this绑定到obj。callapply和bind的区别在于call和apply改变函数的this上下文后,执行函数,而bind返回函数。functionfn(){console.log(this.a);}fn.call({a:3});//3fn.bind({a:4})();//4call和apply区别call和apply的不同的是传入的参数不同。call方法接收几个参数的列表。apply的第一个参数和call一样,第二个参数接收一个包含多个参数的数组。letarr=[2,5,9]console.log(Math.max.call(3,2,5,9))//9console.log(Math.max.call(3,arr))//NaNconsole.log(Math.max.apply(3,arr))//94。newbinding如果使用new构造函数,在函数内部,this指向新创建的对象。functionfoo(){console.log(this);}newfoo();//foo{}foo();//Window{...}这个需要其他情况忽略如果是第三方库的函数使用this,默认绑定会将this指向全局对象,导致不可预知的后果。一种安全的方法是使用显式绑定将函数的this指向一个空对象。functionfoo(){console.log(this);}//创建一个空对象var?=Object.create(null);//使用bind()进行柯里化(Curry)varbar=foo.bind(?);bar();//{}此方法也常用于对象初始化以获得干净且高度可定制的对象。箭头函数箭头函数常用于回调函数中。它会继承父scope的this绑定的对象,相当于ES6之前写的self=this的方式。constpeople={name:"Merry",sayHi(){console.log(this.name)},wait(){setTimeout(()=>{console.log(this.name)})}}people.sayHi()//Merrypeople.wait()//Merry还有一个软绑定(softBind),用的不多,了解一下就好。
