博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
this是什么以及如何判断它
阅读量:7121 次
发布时间:2019-06-28

本文共 3993 字,大约阅读时间需要 13 分钟。

总结下对this的学习与理解

转眼前端的学习已有一年,日常写代码中经常碰到this这个东西。特别是在用vue的时候,this还是有点多的,哈哈。

在翻阅了一部分书籍和一堆大佬的博客后,决定总结一下这些东西,下面谈谈我对this的一些理解,如果有错误,欢迎大家批评指正。如果可以给你带来一些帮助,那是再好不过的了。

1.什么是this

this是在运行时基于函数的执行环境绑定的,它的上下文取决于函数调用时的各种条件。
当一个函数被调用时,会创建一个活动记录(有时候也称执行上下文)。这个记录会包含函数在哪里被调用,函数的调用方法、出今年入的参数等信息。this就是记录其中一个属性,会在函数执行的过程中用到 --你不知道的JavaScript(上)

this实际上是在函数被调用时发生的绑定


2 如何判断this绑定的对象是什么

var name = 'window'const obj1 = {    name:'obj1',  fn(){      console.log(this.name)        }}obj1.fn()//'obj1'
var name = 'window'const obj1 = {    name:'obj1',  fn(){//    "use strict"         console.log(this.name)         }  }const obj2 = {  name:'obj2',  fn2:obj1.fn}obj2.fn2()//'obj2'obj1.fn()//'obj1'

#this的绑定与函数声明的位置没有声明的位置没有任何关系,只取决于函数的调用方式

#一般来说,谁最终调用了函数,那么它就是this的绑定对象。
那在全局下调用函数,this的绑定对象也就是全局对象

var name = 'window'function fn(){   console.log(this.name)}fn()//'window'

下面这种情况为什么不是输出window呢?

var name = 'window'function fn(){ this.name = 'fn'  console.log(this.name)}fn()// 'fn'

也是因为在全局调用这个函数的时候,this.name === window.name就把之前的值给覆盖了,所以输出就是 'fn'。

3. 那么如何判断最终是谁调用了函数

函数调用的形式

var name = 'window'const obj1 = {    name:'obj1',  fn(){//    "use strict"         console.log(this.name)         }  }const obj2 = {  name:'obj2',  fn2:obj1.fn}obj2.fn2()//'obj2'obj1.fn()//'obj1'

还是按照上面的代码为例,这里

obj2.fn2()//完全等价于下面的obj2.fn2.call(obj2)obj1.fn() 等于 obj1.fn.call(obj1)

同样的

var name = 'window'function fn(){ this.name = 'fn'  console.log(this.name)}fn() 等于 fn.call()

这里面call不传入参数,既为undefined。在非严格模式下传入undefined和null,都默认是window。

var name = 'window'function fn(){  'use strict' //为函数开启严格模式 this.name = 'fn'  console.log(this.name)}fn() //则会报错,这也同样说明了函数在js内部调用的形式

改改前面的代码

var name = 'window'const obj1 = {    name:'obj1',  fn(){        this.name = 'fn'      function inFn(){        console.log(this.name)      }       inFn()  }  }obj1.fn()//'window '

上面的inFn()也等同于inFn.call(),在全局调用它,自然也就是输出window了。

关于箭头函数和定时器

首先箭头函数是没有this的 ,它的作用域是和父级的上下文绑定在一起的

var name = 'window'const obj1 = {    name:'obj1',  fn(){        this.name = 'fn'     inFn= ()=>{        console.log(this.name)      }       inFn()  }  }obj1.fn()//'fn'

它的this就是上一层第一个包裹它的普通函数的this

所以用call/bind/apply调用箭头函数的时候,是没有效果的。

var name = 'window'const obj1 = {    name:'obj1',  fn(){        this.name = 'fn'     inFn= ()=>{        console.log(this.name)      }       inFn()  }  }obj1.fn.call(window)//'fn'

这也是为什么在es6后,诸如_this=this这类写越来越少的原因

定时器对this的影响

setTimeout()调用的代码运行在与所在函数完全分离的执行环境上。这会导致,这些代码中包含的 this 关键字在非严格模式会指向 window (或全局)对象,严格模式下为 undefined,这和所期望的this的值是不一样的。--MDN

备注:在严格模式下,setTimeout( )的回调函数里面的this仍然默认指向window对象, 并不是undefined

this.name = 'window'function Foo(){this.name = 'Foo'  this.fn = function(){    console.log(this.name)  }  this.timer = function(){    setTimeout(this.fn)  }}var obj = new Foo()obj.timer()//'window'

可以使用call/apply/bind调用改变this绑定对象。

this.name = 'window'function Foo(){this.name = 'Foo'  this.fn = function(){    console.log(this.name)  }  this.timer = function(){    setTimeout(this.fn.call(this))  }}var obj = new Foo()obj.timer()//'Foo'

还有箭头函数

this.name = 'window'const obj = {  name:'obj',  fn(){    console.log(1)    setTimeout(()=>{      console.log(this.name)    },1000)  }}obj.fn()//'obj'

也就是说从优先级上说,有箭头函数和定时器就不判断是否由call/apply/bind调用

new对this的影响

new的优先级很高,在没有定时器影响的情况下是最高的

this.name = 'window'function Foo(){this.name = 'Foo'  this.fn = function(){    console.log(this.name)  }  this.timer = function(){    setTimeout(this.fn)  }}var obj = new Foo()obj.timer() //'window'定时器

只要是由new调用的,就绑定到新创建的对象,其他情况似乎都无法再改变this绑定的对象。

1.箭头函数

function Foo(){  this.name='Foo'  this.fn = ()=>{    console.log(this.name)  }  }var foo = new Foo()this.name = 'window'  //设置一下window.name的值      foo.fn()    //'Foo' 输出的是实例变量console.log(this.name)//'window'  并没有改变window.name的值

2.call/bind/apply

this.name = 'window'function Foo(){  this.name='Foo'  this.fn = ()=>{    console.log(this.name)  }  }var foo = new Foo()foo.fn.call(window)//'Foo'  const tes = foo.fn.bind(window)tes()  //'Foo'

##也就是说判断一个运行中的this绑定,就要找到这个函数的直接调用位置。

##按照上面介绍的优先级顺序进行判断便可以找到this的绑定对象。

转载地址:http://reiel.baihongyu.com/

你可能感兴趣的文章
如何处理IE首页被篡改的问题
查看>>
思科网络设备模拟器GNS3与SecureCRT关联
查看>>
Activemq判断队列存活脚本(一)
查看>>
系统状态检测 及进程控制
查看>>
xen-tools创建虚拟机找不到root fs的解决办法
查看>>
IBM X3650 M4 服务器
查看>>
备份和归档的区别
查看>>
shell基础
查看>>
linux 文件类型 时间戳 ls bash特性四 文件查看命令 cp move echo
查看>>
如何在XenDesktop中映射USB设备
查看>>
Java并发编程 基础知识学习总结
查看>>
我又发现一个直接就能安装中文小红帽的方法
查看>>
ACM弱校ACMer A HDU1045Fire Net有感
查看>>
cxgrid实现分组统计和添加Footer
查看>>
刘敏华:2013年网络营销行业展望
查看>>
理解MySQL——架构与概念
查看>>
vsftpd虚拟用户
查看>>
ionic 幻灯指令 ion-slide-box
查看>>
发一个经典的Flask-SQLAlchemy使用场景
查看>>
iOS逆向之自动化重签名
查看>>