this 指向问题及优先级

1、函数是和new一起被调用的吗(new绑定)?如果是,this就是新构建的对象。

var bar = new foo()

2、函数是用call或apply被调用(明确绑定),甚至是隐藏在bind 硬绑定 之中吗?如果是,this就是明确指定的对象。

var bar = foo.call( obj2 )

3、函数是用环境对象(也称为拥有者或容器对象)被调用的吗(隐含绑定)?如果是,this就是那个环境对象。

var bar = obj1.foo()

4、使用默认的this(默认绑定)。如果在strict mode下,就是undefined,否则是global对象。

var bar = foo()

【注:】 箭头函数中,this 指向声明函数时,最靠近箭头函数的普通函数的 this

从函数对象,活动对象,执行上下文内容对象角度解释 this 指向

this 引用的是函数执行时的执行上下文对象Scope属性维护的作用域链中的当前活动对象【即栈顶】的父级活动对象

this 指向调用函数时的对象。在全局执行时,则是全局对象。

箭头函数的this指向的是谁调用箭头函数的外层function,箭头函数的this就是指向该对象,如果箭头函数没有外层函数,则指向window。

【谁调用箭头函数的外层function,箭头函数的this就是指向该对象;
如果箭头函数没有外层函数,则指向window 】的理解:

function Caller(name){
    this.name = name;
    this.wrapFunc = function(){
        return () => console.log(this.name);
    }
}

let caller = new Caller('foo');
caller.wrapFunc(); // foo

1. caller 对象调用了 外层函数wrapFunc
2. 外层函数wrapFunc 的 this 指向 caller
2. 箭头函数中的 this 指向外层函数 wrapFunc 的 this

箭头函数

箭头函数会捕获其所在上下文的 this 值,作为自己的 this 值。

箭头函数的this,因为没有自身的this,所以this只能根据作用域链往上层查找,直到找到一个绑定了this的函数作用域(即最靠近箭头函数的普通函数作用域,或者全局环境),并指向调用该普通函数的对象。

或者从现象来描述的话,即箭头函数的this指向声明函数时,靠近箭头函数的普通函数的this。但这个this也会因为调用该普通函数时环境的不同而发生变化。导致这个现象的原因是这个普通函数会产生一个闭包,将它的变量对象保存在箭头函数的作用域中。

参考链接

【第1258期】从JS垃圾回收机制和词源来透视闭包

【第1047期】重新认识JS的this、作用域、闭包、对象

var name = 'window'

var person1 = {
  name: 'person1',
  show1: function () {
    console.log(this.name)
  },
  show2: () => console.log(this.name),
  show3: function () {
    return function () {
      console.log(this.name)
    }
  },
  show4: function () {
    return () => console.log(this.name)
  }
}
var person2 = { name: 'person2' }

person1.show1()                   // person1
person1.show1.call(person2)       // person2

person1.show2()                   // window
person1.show2.call(person2)       // window

person1.show3()()                 // window
person1.show3().call(person2)     // person2
person1.show3.call(person2)()     // window

person1.show4()()                 // person1
person1.show4().call(person2)     // person1
person1.show4.call(person2)()     // person2

var name = 'window'

function Person (name) {
  this.name = name;
  this.show1 = function () {
    console.log(this.name)
  }
  this.show2 = () => console.log(this.name)
  this.show3 = function () {
    return function () {
      console.log(this.name)
    }
  }
  this.show4 = function () {
    return () => console.log(this.name)
  }
}

var personA = new Person('personA')
var personB = new Person('personB')

personA.show1()                   // personA
personA.show1.call(personB)       // personB

personA.show2()                   // personA
personA.show2.call(personB)       // personA

personA.show3()()                 // window
personA.show3().call(personB)     // personB
personA.show3.call(personB)()     // window

personA.show4()()                 // personA
personA.show4().call(personB)     // personA
personA.show4.call(personB)()     // personB

隐含绑定的丢失

尽管bar是obj.foo的引用,但实际上它只是另一个foo自己的引用而已(浅拷贝,将函数对象foo在内存中的堆地址拷贝给bar变量);最后起作用的调用点是bar(),处于全局环境中。

function foo(){
    console.log(this.name);
}

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

var name = 'window';

var bar = obj.foo;

obj.foo(); // '2'
bar();     // 'window'

参考链接【第765期】你不懂JS:this豁然开朗!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值