十五、this 的值详解

var obj = {

  foofunction(){

    console.log(this)

  }

}

 

var bar = obj.foo

obj.foo() // 打印出的 this 是 obj

bar() // 打印出的 this 是 window


请解释最后两行函数的值为什么不一样。


首先需要从函数的调用开始讲起。


JS(ES5)里面有三种函数调用形式:


func(p1, p2)

obj.child.method(p1, p2)

func.call(context, p1, p2) // 先不讲 apply


一般,初学者都知道前两种形式,而且认为前两种形式「优于」第三种形式。


从看到这篇文章起,你一定要记住,第三种调用形式,才是正常调用形式:


func.call(context, p1, p2)


其他两种都是语法糖,可以等价地变为 call 形式:


func(p1, p2) 等价于

func.call(undefined, p1, p2)

 

obj.child.method(p1, p2) 等价于

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


请记下来。(我们称此代码为「转换代码」,方便下文引用)


至此我们的函数调用只有一种形式:


func.call(context, p1, p2)


这样,this 就好解释了


this,就是上面代码中的 context。就这么简单。


this 是你 call 一个函数时传的 context,由于你从来不用 call 形式的函数调用,所以你一直不知道。


先看 func(p1, p2) 中的 this 如何确定:


当你写下面代码时


function func(){

  console.log(this)

}

 

func()


等价于


function func(){

  console.log(this)

}

 

func.call(undefined) // 可以简写为 func.call()


按理说打印出来的 this 应该就是 undefined 了吧,但是浏览器里有一条规则:


如果你传的 context 就 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)

因此上面的打印结果是 window。


如果你希望这里的 this 不是 window,很简单:


func.call(obj) // 那么里面的 this 就是 obj 对象了


再看 obj.child.method(p1, p2) 的 this 如何确定


var obj = {

  foofunction(){

    console.log(this)

  }

}

 

obj.foo()


按照「转换代码」,我们将 obj.foo() 转换为


obj.foo.call(obj)


好了,this 就是 obj。搞定。


回到题目:


var obj = {

  foofunction(){

    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( ),虽然后者的语法错了,但是形式与转换代码里的 obj.child.method(p1, p2) 对应上了,于是就可以愉快的转换了:


  arr[0]()

假想为    arr.0()

然后转换为 arr.0.call(arr)

那么里面的 this 就是 arr  :) 


总结


  1. this 就是你 call 一个函数时,传入的 context。

  2. 如果你的函数调用形式不是 call 形式,请按照「转换代码」将其转换为 call 形式。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值