【JS】关于this

this到底是什么?

首先纠正两个错误观点:this既不指向自身也不指向函数的词法作用域!

this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。也就是说this是在函数被调用时发生绑定的,它指向什么完全取决于函数在哪里被调用

当一个函数被调用时,会创建一个活动记录(执行上下文,包含函数在哪里被调用(调用栈)、函数调用方式、传入的参数等信息),this就是这个记录的一个属性,会在函数执行的过程中用到。

this的绑定规则

1、默认绑定

在非严格模式下,this默认绑定到全局对象;严格模式下绑定到undefined。

2、隐式绑定

当函数在某个上下文对象中调用时,this绑定到这个上下文对象,类似obj.foo()。

注意:回调函数中经常出现丢失this绑定的现象!以及下面几种现象:

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

function doFoo(fn) {
    fn();
}

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

var bar = obj.foo; // 函数别名

var a = 'global a';

bar(); // 'global a'
doFoo(obj.foo); // 'global a' // 参数传递其实就是一种隐式赋值

3、显式绑定

通过call(..)、apply(..)方法的第一个参数,直接指定this的绑定对象。apply和call的区别在于参数:call(this, arg1, arg2,...),apply(this, [arg1, arg2,...])。

硬绑定bind(..),会返回一个硬编码的新函数,将你指定的参数设置为this的上下文并调用原始函数。

// 简单的示意bind函数
function bind(fn, obj) {
    return function() {
        fn.apply(obj, arguments);
    }
}

4、new绑定

JavaScript中,“构造函数”其实就是被new操作符调用的普通函数。所以其实只有对函数的“构造调用”。

使用new调用函数时,会自动执行下面的操作:

  1. 创建一个新对象
  2. 这个新对象会被执行[[Prototype]]连接
  3. 这个新对象会被绑定到函数调用中的this
  4. 如果函数没有返回其他对象,那么会自动返回这个新对象
function foo(a) {
    this.a = a;
}

var bar = new foo(2); //构造一个新对象并将它绑定到foo(..)调用中的this
bar.a; // 2

绑定规则的优先级

  1. 函数是否在new中调用(new绑定)?如果是的话this绑定到新创建的对象。
  2. 函数是否通过apply、call(显式绑定)或者bind(硬绑定)调用?如果是的话this绑定到指定对象。
  3. 函数是否在某个上下文中被调用(隐式调用)?如果是,this绑定到那个上下文对象。
  4. 如果都不是,采用默认绑定,严格模式下绑定到undefined,否则绑定到全局对象。

ES6的箭头函数

不会使用上诉绑定规则,而是根据词法作用域来决定this,就是说箭头函数会继承外层函数调用的this绑定。

function foo() {
    return () => {
        console.log(this.a); // this继承自foo()
    }
}

var obj1 = { a: 1 };
var obj2 = { a: 2 };

var bar = foo.call(obj1);
bar.call(obj2); // 1

本文参考:《你不知道的JavaScript(上)》---- [美]KYLE SIMPSON

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值