javascript this 指向问题(隐式绑定、显示绑定、箭头函数)

四种绑定规则

1、默认绑定规则:this 指向 window。

2、隐式绑定规则:谁调用就指向谁。

3、显式绑定规则:this 指向 call、apply、bind 函数的第一个传参。

4、new 绑定规则:this 指向构造函数产生的对象。

 

1、默认绑定规则

// 全局中的 this 指向 window
console.log(this === window) // true
​
// 函数独立调用,函数内部的 this 指向 window
function func() {
    console.log(this === window) // true
}
func() // 等同于 window.func,即,函数 func 的调用者是 window

 

2、隐式绑定规则

var obj = {
    a: 'aaa',
    b: function() {
        console.log(this) // 指向 obj
​
        function c() {
            console.log(this) // 指向 window
        }
        c() // 这里可以理解为函数的独立调用,也可以理解为函数调用时产生了 AO 对象,AO 对象中默认的 this 指向 window。
        
        ;(function(){
            console.log(this) // 指向 window,原理同上
        })()
        
        return function(){
            console.log(this) // 指向 window,原理同上,obj.b() 需要变成 obj.b()(),可以把return function 拆分成两步,var d = function...,return d,这样就很明显的能看出,“闭包”的调用实际上就是 d(),也就是函数的独立调用。
        }
    }
}
obj.b() // 这里可以理解为谁调用就指向谁,也可以理解为函数调用产生了 AO 对象呢,AO 对象中默认的 this 指向 window,但是函数是被 obj 对象调用的,因此触发了隐式绑定规则,this 指向改变,指向了 obj。
// 隐式绑定规则失效的情况
var obj = {
    a: 'aaa',
    b: function(){
        console.log(this)
    }
}
​
// 一、变量赋值导致隐式绑定规则失效
var bar = obj.b
bar() // 这里 this 指向 window。虽然看起来任然是 obj.b() 这样执行,但是当 obj.b 赋值给 bar 变量后,指向就变了,bar() 等同于 window.bar(),所以调用者为 window
​
// 二、函数传参导致隐式绑定规则失效
function foo(fn){
    fn() // 类似于独立调用
}
foo(obj.b) // 这里 this 指向 window。实参传递给形参的过程,是值的浅拷贝,fn 和 obj.b 是两个不同的引用对象,因此 fn() 可以理解为单独调用。在函数 foo 内部添加如下代码可以证明这一点:
// obj.b = function() {
//     console.log('我变了')
// }
// console.log(fn) // 我没变
// 父函数有能力决定子函数的 this 指向
function foo(fn){
    new fn() // 这时 this 指向了 obj.b 这个构造函数 new 出来的对象
    fn.bind(obj)() // 这时 this 指向了 obj
}
foo(obj.b)
​
// forEach 函数的第二个参数传递 this 指向对象
var arr = [1, 2, 3]
arr.forEach(function(){
    console.log(this) // this 指向了 obj
}, obj)

 

3、显式绑定规则

func.call(obj, args1,  args2, args3 ...) // this 指向 obj
func.apply(obj, [args1, args2, args3 ...]) // this 指向 obj
func.bind(obj, args1,  args2, args3 ...)() // this 指向 obj
​
// 注意,当绑定对象为 undefined 或 null 时,由于这个参数必须是 Object 类型,而 undefined 和 null 没有包装类可以转换,就会触发静默失败,就会采取默认绑定方式,默认绑定方式即绑定 window 对象。
func.call(undefined) // this 指向 window
func.call(null) // this 指向 window
func.call(1) // this 指向 Number {1} 对象

 

4、new 绑定规则

function Person(){
    console.log(this) // this 指向 person 实例
}
var person = new Person()
​
// 构造函数默认返回 this,如果改变 return 的值,那么,返回引用类型将改变返回值,其他情况返回 this
function Person(){
    return 1 // 返回的还是 this
    return [] // 返回的是 []
    return {} // 返回的是 {}
    return undefined // 返回的还是 this
    return null // 返回的还是 this
}
var person = new Person()
console.log(person)

 

四种绑定规则的优先级

4 > 3 > 2 > 1

 

箭头函数的 this 指向问题

箭头函数体内部没有 this 指向问题,因此,箭头函数中使用的 this 其实是箭头函数外层代码的 this。

四种绑定规则对箭头函数无效。

箭头函数不能用 new 关键词,会报错。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值