你不知道的this指向

JS中的this指向一直困扰着很多人,要弄清楚this的绑定过程,就要先找到函数被调用的位置,就是为了到达当前执行位置所调用的所有函数.针对不同的调用位置具体分析,有以下四种绑定规则:

1.默认绑定

独立函数调用,无法应用其他规则时的默认规则.

function foo(){
    console.log(this.a)
}
var a = 2
foo() // 2
复制代码

非严格模式下,默认绑定this指向全局对象,严格模式下this绑定到undefined.

"use strict";
function foo(){
    console.log(this.a)
}
var a = 2
foo() // TypeError: this is undefined
复制代码

2.隐式绑定

判断调用位置是否有上下文对象

function foo(){
    console.log(this.a)
}
var obj = {
    a: 2,
    foo: foo
}
var a = 3
obj.foo() // 2
复制代码

无论函数声明在对象内部还是独立声明,当函数调用有上下文对象时,隐式绑定会把this绑定到这个上下文对象.

隐式丢失

看了上面两条感觉很简单对不对,那么再看看下面这段代码:

function foo(){
    console.log(this.a)
}
var obj = {
    a: 2,
    foo: foo
}
var a = 3
var bar = obj.foo
bar();  // 3
复制代码

和上面极其相似的写法,为什么会产生不懂的结果?

原因就在于 bar 虽然是 obj.foo的引用,但本质上引用的是 foo函数本身,因此实际上bar()是一个无上下文的独立函数调用,应用默认绑定.

类似的情况同样发生在回调函数中:

var a = 123
var obj = {
    a: 56,
    foo: function(){
        console.log(this.a)	
    }
}
setTimeout(obj.foo,1000)  //123
复制代码

参数传递也是一种隐式赋值,原理与上面的例子相同,引用的是函数本身.

3.显式绑定

使用 call,apply方法强制在某个对象上调用函数,this指向该对象

function foo(){
    console.log(this.a)
}
var obj = {
    a: 2
}
var a = 3
foo.call(obj) // 2
复制代码

bind硬绑定

bind函数接收要绑定的对象,返回一个硬编码的新函数,并把指定的对象设置为this的上下文,并调用原始函数.

function foo(){
    console.log(this.a)
}
var obj = {
    a: 2
}
var a = 3
var bar = foo.bind(obj) 
bar() // 2
复制代码

API 调用上下文

第三方库的一些函数和js宿主环境内置函数提供了一个可选的参数,称为'上下文',作用和bind函数一样,确保你的回调函数使用正确的this

function foo(el){
    console.log(el, this.id)
}
var obj = {
   id: 'cool'
}
[1,2,3].forEach(foo,obj)  //1 cool 2 cool  3 cool 
复制代码

4.new 绑定

在传统面向类语言中,如java,new操作符被用来实例化一个类,而在js中,实现的机制完全不同 obj = new foo(), foo只是一个被new操作符调用的普通函数,使用new 操作符时会发生下面的操作

  • 创建一个全新的对象
  • 对这个新对象执行[[prototype]]连接
  • 这个新对象指向函数调用的this
  • 如果函数没有返回其他对象,那么函数执行完毕会自动返回这个新对象

以上四条规则的优先级是 new > 显示 > 隐式 > 默认

一些例外情况

箭头函数

箭头函数的this在函数定义时绑定,指向父执行上下文.

var x=11;
var obj={
 x:22,
 y:()=>{
   console.log(this.x);
 }
}
obj.y();
//输出的值为11
复制代码

这里箭头函数以键值对的方式定义,作为对象 obj 的一个属性,因此this指向定义obj的上下文 window

被忽略的this

向call,apply,bind函数传入 null 或者undefined,在调用时会被忽略,实际应用的时默认绑定规则.

function foo(){
    console.log(this.a)
}
var a = 2
foo.apply(null) //2
复制代码

转载于:https://juejin.im/post/5a97a411f265da4e95191cb7

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值