揭开this面纱

目录

为什么要使用this?

this提供了一种更优雅的方式来隐式“传递”一个对象的引用,使用this,函数可以自动引用合适的上下文对象。

this到底是什么?

this是一种机制,在js运行时进行上下文绑定,this的绑定与函数声明位置没有关系,只取决于函数的调用方式。

更确切的说,this实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。

如何判断this?

this的四种绑定规则:new绑定、显示绑定、隐式绑定、默认绑定。优先级由高——>低

  1. 函数使用new调用,this指向新创建的对象
   var Obj = new Foo() // this -> Obj 
  1. 函数通过apply、call显示绑定,this指向指定对象
   var Obj = foo.call(Obj2) // this -> Obj2
  1. 函数在上下文对象中调用(隐式绑定),this指向上下文对象
   var Obj = obj1.foo() // this -> obj1
  1. 默认规则:独立函数调用,若foo函数体内(并不是调用foo的位置)声明了处于严格模式下,this指向undefined,否则绑定到window
    var Obj = foo()

需要注意的是,隐式绑定会出现丢失绑定对象的情况,根本原因其实是隐式赋值引起的。

看如下例子:

function foo(){
    console.log(this.a)    
}

var  obj = {
    a: 2,
    foo: foo
}

var a = 'some'
  1. 函数被别名
var bar = obj.foo
bar() // 'some'
  1. 函数被用作参数传递
function baz(fn){
    fn() //这里是真正调用foo的位置,this指向全局作用对象
}
 baz(obj.foo) // 'some'
  1. 在js内置函数中
    setTimeout(obj.foo , 1000) // 'some'
  1. 间接引用
    //这里还是以上面的栗子为前提,新增下面代码
    var obj2 = {
        a: 3
    }
    obj.foo() // 2
    (obj2.foo = obj.foo)() // 'some'
    

obj2.foo = obj.foo表达式的返回值其实是foo的引用,再执行foo()

前三种情况,其实都隐藏了一个赋值操作: fn = obj.foo ,这里fn引用的是foo函数本身。之后直接调用fn(),很显然这里使用默认规则。

综上:找准函数被调用的真实位置是关键之处,然后应用四条规则及优先级,判定this最终指向。

tips

在apply/call中指定对象为null或者undefined时,这时this使用默认规则,如:

“展开”一个数组

function foo(a,b){
    console.log("a:",a,"b:",b)
}
foo.apply(null, [1,2])

这里并不关心this的指向,但是还是需要一个占位值,但是更安全的做法还是将this指向一个特殊的空对象,如:
foo.apply(Object.create(null), [1, 2])

ES5硬绑定bind()函数

ES5的bind()返回一个硬编码的新函数,固定了this的指向。

bind()实现原理类似,创建一个包裹函数,内部手动调用显示绑定apply/call

ES6箭头函数不使用this的四种规则

箭头函数根据外层作用域来决定this指向。

相较于传统的this机制:类似于一种动态作用域,在运行时,被调用的位置处确定绑定对象。

ES6的箭头函数根据当前的词法作用域来决定this,即继承外层函数调用的this绑定。

栗子:

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

    var obj = {
        a: 1
    }

    var obj1 = {
        a: 2
    }
    var bar = foo.call(obj)
    bar.call(obj1) // 1

this指向外层函数foo调用时的对象.

在ES6之前就有一种方案实现了和箭头函数一样的功能

 function foo() {
    var self = this
    return function () {
        console.log(self.a)
    }
}

参考图书:《你不知道的JavaScript上卷》.中国工信出版集团.黄宝书

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值