JS中的this

92 阅读2分钟

0 核心思想

  1. this永远指向函数的直接调用者
  2. 如果有new关键字,则this指向new出来的对象
  3. 在事件中,this指向触发这个事件的对象(IE例外)

一般来说,函数的调用有以下几种方式

func(p1, p2) 
obj.child.method(p1, p2)
func.call(context, p1, p2)

可以将前两种都转化为最后一种进行表达,也就是说this实际执行的就是函数调用时传入的上下文,根据调用时传入的上下文对象决定this

常见问题1

var obj = {
  foo: function(){
    console.log(this)
  }
}

var bar = obj.foo
obj.foo() // 转换为 obj.foo.call(obj),this 就是 obj
bar() 
// 转换为 bar.call()
// 由于没有传 context
// 所以 this 就是 undefined
// 最后浏览器给你一个默认的 this —— window 对象

[ ] 语法

function fn (){ console.log(this) }
var arr = [fn, fn2]
arr[0]() // 这里面的 this 又是什么呢?

可以将数组下标按下面代码的方式转换

        arr[0]() 
假想为    arr.0()
然后转换为 arr.0.call(arr)
那么里面的 this 就是 arr 了 :)

箭头函数

不影响this,直接将上一级的结果传递进来。 举例

function a() {
    return () => {
        return () => {
        	console.log(this)
        }
    }
}
console.log(a()()())

this在本质上是最外层的this指向,即window

call, apply, bind

首先分析作用相似的call, apply

  • call 和 apply 都是为了解决改变 this 的指向。作用都是相同的,只是传参的方式不同。
  • 除了第一个参数外,call 可以接收一个参数列表,apply 只接受一个参数数组
let a = {
    value: 1
}
function getValue(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value)
}
getValue.call(a, 'yck', '24')
getValue.apply(a, ['yck', '24'])

bind参数与call类似,但返回的是函数

let a = {
    value: 1
}
function getValue(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value)
}
getValue.bind(a, 'yck', '24')()

连续bind的结果由第一次bind决定

let a = {}
let fn = function () { console.log(this) }
fn.bind().bind(a)() // => ?

可以将bind转化为返回函数的apply形式

// fn.bind().bind(a) 等于
let fn2 = function fn1() {
  return function() {
    return fn.apply()
  }.apply(a)
}
fn2()

image.png

总结

this执行主体,谁把它执行的和在哪创建的在哪执行的都没有必然的关系

  • 函数执行,看方法前面是否有点,没有点thiswindow(严格模式下是undefined),有点,点前面是谁·this·就是谁
  • 给当前元素的某个事件行为绑定方法,当事件行为触发,方法中的this是当前元素本身(排除IE的attachEvent
  • 构造函数体中this是当前类的实例
  • 箭头函数中没有执行主体,所用到的this都是所处上下文中的this
  • 可以基于Function.prototype上的call/apply/bind改变this指向