了解this 怒推面试官一波

186 阅读2分钟

[TOC]

基本知识

this在JavaScript中属于经常使用的一个对象。在定义中,在Javascript中this总是指向调用它所在方法的对象,谁发起了调用,this将指向谁。

下面将描述一些案例,带领大家了解this

全局情况下的this

function test () {
    console.log(this)
}
test()

直接输出了window对象,因为JS在查找的时候,发现this的指向是undefined,那么在JS会将this指向到window上。

"use strict"
function test () {
    console.log(this)
}
test()

严格模式下,JS是不会将this指向到window上,所以输出是undefined

Alt text

调用情况下的this

var obj = {
    name:'hero'
}
function test () {
    console.log(this)
}
obj.test = test
obj.test()

这个代码很好的展示了,由谁调用,this就会被指向调用方所在对象。

Alt text

现在我们来思考一下,这种情况。

var obj = {
    name:'hero',
    proxy:{
        name:'proxy hero'
    }
}
function test () {
    console.log(this)
}
obj.proxy.test = test
console.log('obj.proxy.test')
obj.proxy.test()

var _p = obj.proxy
console.log('_p.test')
_p.test()

这里并没有发生你们预想的

obj.proxy.test
{name: "hero", proxy: {name: "proxy hero", test: ƒ}}
 _p.test
{name: "proxy hero", test: ƒ}

而是

obj.proxy.test
{name: "proxy hero", test: ƒ}
 _p.test
{name: "proxy hero", test: ƒ}

这个例子表明了,this的绑定只受到最近的成员影响。所以,此时的this被绑定在proxy上。

call,apply,bind的this

var obj = {
    name:'hero',
    test (postString) {
        console.log(this,postString)
    }
}
var obj2 = {name:'super hero'}
obj.test.call(obj2,'call')
obj.test.apply(obj2,['apply'])

call,apply的机制是一样的,都是直接修改了内部this的指向。唯一的区别是call传入参数是挨个传入,apply是传入一整个参数数组。

Alt text

var obj = {
    name:'hero',
    test (postString) {
        console.log(this,postString)
    }
}
var obj2 = {name:'super hero'}
obj.test.bind(obj2)('bind')

bind的机制与其他两个是不一样的,通俗的来说,就是bind设置之后,是蓄势待发。需要正常的执行,才能运行。这在react中经常使用。

在ES6提案中,你还可以使用这种方式进行bind。

// 函数绑定运算符是并排的两个冒号(::)
var k = obj2::obj.test
k('::bind')

这个提案,现在暂时只有babel支持。

参考资料

developer.mozilla.org/zh-CN/docs/…