分情况讨论
有一句话说“谁调用它,this就指向谁”,细细想这句话,其实还是有点道理,但是更加稳妥的和准确的判断方法必然是按照实际情况来先来预设几种情况,以及他们的this指向
- 默认绑定 浏览器中函数体内的this默认绑定到全局对象window当中,node环境下是Gobal对象,use strict下两个都是undefined
- 隐式绑定 如果函数调用时,前面存在调用它的对象,那么this就会隐式绑定到这个对象上,也就是常说的通过上下文对象调用的方式
- 显式绑定 使用call,apply,bind方法
- new绑定 使用new方法调用构造函数创建对象
- 箭头函数绑定 箭头函数没有自己的this,它的this是派生来的
默认绑定
这个比较简单,我直接列出两段代码就好了
Code1 function Func1(){ console.log(this) } Func1() function Func2(){ "use strict"; console.log(this) } Func2() /* output: Func1 Object [global] { ....... } Func2 undefined */复制代码
Code2 const Obj1 = { apple: 10, fn: function(){ console.log(this.apple) } } var fn1 = Obj1.fn fn1() //undefined复制代码
第二段代码注意因为最后是fn1去调用,所以它的this就是全局,但是全局上并没有挂载到apple这个属性所以是undefined
隐式绑定,上下文对象调用里面的this
先看一个简单的例子
这段代码存在着一个嵌套关系父对象里面嵌套着子对象,那么在最终调用的时候,this会指向调用它的对象,看到这相信大家已经明白上下文调用里面的this逻辑了吧,那我们再来一道综合题巩固一下吧,大家先猜猜下面的输出是啥
答案 FE BE undefined
- 第一个很简单,就是指向调用它的对象
- 第二个的fn虽然拿的是oj1的但是它在调用的时候还是在oj2里面调用的所以输出还是BE
- 第三个相当于默认绑定的例子,它返回的fn()是在全局环境下执行的,全局没有绑定name所以自然是undefined
通过这两个例子你懂上下文对象调用的this了吗。
使用call,apply,bind方法显式绑定
- call() obj.fn.call(obj1,'args',,)
- apply() obj.fn.call(obj1,[...args])
- bind() obj.fn.call(obj1,'args',,)
这三个函数表示把obj的fn函数的this指向obj1并传递对应参数,call,apply会是直接调用参数的传递方式有点不同,bind则是返回一个新函数不会直接被调用
关于这几个函数的使用我就不给例子了,干脆直接写一个call加强印象吧????
只是给出个主要思路细节方面还要完善的
箭头函数的this
箭头函数的this是由其所属函数或全局作用域决定的,本质来说Arrow Function并没有自己的this,它的this是派生而来的,根据“词法作用域”派生而来,简单来说,所谓的词法作用域就是一个变量的作用在定义的时候就已经被定义好,当在本作用域中找不到变量,就会一直向父作用域中查找,直到找到为止
看了这段话,相信大家大概也能明白箭头函数的指向了吧,我再用一个例子对比一下,看完你肯定明白了!
注意箭头函数的绑定无法被修改,第一次绑定了谁那么就是谁了
看看那两个外部调用的例子,箭头函数的this还是指向包住它函数作用域,而普通函数谁调用它它就指向谁,是不是很简单呢!
new操作符执行构造函数时究竟做了什么呢
- 创建一个新对象
- 将构造函数的this指向新对象
- 添加相应属性
- 返回新对象
function Demo(params) { this.name = 'lavie' } var son = new Demo() console.log(son.name)// lavie复制代码
注意当构造函数return一个对象的时候,this指向这个返回的对象
function Demo(params) { this.name = 'lavie' const instance = { name: 'papa' } return instance } var son = new Demo() console.log(son.name)// papa复制代码
优先级问题
这个没啥好说的记住就行????
显式绑定 > 隐式绑定 > 默认绑定
new绑定 > 隐式绑定 > 默认绑定
写作不易对大家有帮助的话给小菜鸡一个赞呗嘻嘻