不一样的 this 题目

JS 的 this 指向题目是陈词滥调的难点了。我当初从 Java 转过来时极为不适应,花了好长时间才挣脱这个暗影。网上也有许多关于 this 的文章了,本文就简朴说说,再聊点不一样的。

this 主如果在函数中运用,在函数外运用的话,一概指向全局对象
console.log(this)    // window

var o = {
  global: this       // window
}

在函数内运用 this 时,细致指向是由函数的挪用体式格局决议,而不是依据函数定义体式格局决议

1. 函数作为一般函数运转时,能够看作是当作全局对象的要领运转,此时 this 指向全局对象
function hello() {
  console.log(this)
}
hello()    // window 作为一般函数运转
2. 函数作为对象的要领挪用时,函数内的 this 指向该对象

所以上面一条,一般函数能够看作是全局对象的要领,所以 this 指向全局对象

var name = 'global'

var obj = {
  name: 'local',
  getName: function () {
    console.log(this.name)
  },
  outer: function () {
    function inner() {
      console.log(this.name) 
    }
    inner()      // 这是第 12 行代码
  }
}

obj.getName()    // local 作为 obj 的要领挪用,此时 this 指向 obj
obj.outer()      // 打印什么?控制台尝尝吧

这里提到了一个人人轻易无视的点: 嵌套函数
还记得上面题目说的吗? this 的指向是由函数的挪用体式格局来决议的

由于大多数嵌套函数是直接被挪用的, 比方:第 12 行代码,挪用 inner()
这时刻 inner 是被当作一般函数挪用的,也能够看作是 window.inner() ,所以此时 inner 内部的 this 指向 window,打印 global

罕见的解决方案以下:

var obj = {
  name: 'local',
  outer: function () {
    var that = this
    function inner() {
      console.log(that.name) 
    }
    inner()
  }
}

// 声明变量 that ,在 inner 内部用 that 替代 this
obj.outer()    // local

另有个题目

var name = 'global'
var obj = {
  name: 'local',
  getName: function () {
    console.log(this.name)
  }
}

obj.getName()    // local
var getName = obj.getName
getName()     // ?

直接挪用 getName() 会打印 global
照样前面说的,虽然 obj.getName() 在声明的时刻是作为 obj 的要领
然则把它赋值给 getName, 再挪用 getName() 和 obj.getName() 的挪用体式格局已差别了

3. apply call bind 转变 this 指向

这个没啥还说的,强迫转变 this 的指向,bind 的优先级最高。

var name = 'global'
var obj = {
  name: 'local',
  getName: function () {
    console.log(this.name)
  }
}

var obj2 = {
  name: 'xiaoming'
}

var obj3 = {
  name: 'laowang'
}

obj.getName()     // local
obj.getName.call(obj2)    // xiaoming

var getName = obj.getName.bind(obj3)    // 将 getName 内部的 this 绑定到 obj3
getName()     // laowang 不再是 window

getName.call(obj2)    // laowang
                      // bind 不会遭到 apply 和 call 影响
4. 定时器设置的函数,this 会指向全局
var name = 'global'
var obj = {
  name: 'local',
  getName: function () {
    console.log(this.name)
  }
}

var obj3 = {
  name: 'laowang'
}

setTimeout(obj.getName, 1000)            // global
setTimeout(obj.getName.bind(obj3), 2000) // laowang

bind 强迫绑定优先级最高,不受定时器影响
准确挪用体式格局以下:
外面包一层匿名函数

setTimeout(function () {
  obj.getName()
}, 1000)            // local
5. ES6 箭头函数

ES6 推出了箭头函数,细致教程能够参考阮一峰先生的教程
箭头函数没有本身的 this 和 arguments, 因此在箭头函数内部运用 this 和 argments, 实在运用的是外层的 this 和 arguments

var name = 'global'
var obj = {
  name: 'local',
  getName: () => console.log(this.name),
  outer: function () {
    var inner = () => console.log(this.name)
    inner()
  }
}
obj.getName()    // global 由于箭头函数没有本身的 this,所以 getName 内部的 this 实际上是函数外部的 this,指向全局
obj.outer()      // local

作为函数的要领,最好不要用箭头函数,由于箭头函数内部的 this 不再指向该对象。
所以箭头函数虽然好用,然则不要滥用哦

箭头函数还常用于数组的 forEach/map/some/every/filter/reduce 等轮回要领中,比方

var arr = [1, 2, 3].map(item => item * 2)
    原文作者:syaka
    原文地址: https://segmentfault.com/a/1190000007862917
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞