this是什么以及怎样推断它

总结下对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的绑定对象。

    原文作者:seeker
    原文地址: https://segmentfault.com/a/1190000018202016
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞