this全面解析(二)

上篇文章this全面解析(一)中,我们说了几个常见的错误认识。

接下来,我们来看看this到底是一种什么样的机制

this是运行时绑定,并不是在编译时,上下文取决于函数调用时的各种条件。this绑定和函数的声明位置没有任何关系,只取决于函数的调用方式。

调用位置

调用位置是函数在代码中被调用的位置(不是声明的位置)。

一般来说,寻找调用位置就是找“函数被调用的位置”,但这并不一直是一件简单事,有些时候,编程模式会隐藏真正的调用位置。

不过我们还是有办法的!我们可以通过分析调用栈(为了达到当前执行位置所调用的所有函数),那么我们关心的,就是当前执行函数的前一个调用中。

function baz() {
    //当前调用栈:baz
    //调用位置是全局作用域
    console.log('baz');
    bar(); //bar 的调用位置
}

function bar() {
    //当前调用栈 baz--> bar
    //因此当前调用位置在 baz 中
    console.log('bar');
    foo(); // foo的调用位置
}

function foo() {
    //当前调用栈 baz-> bar ->foo
    //当前调用位置在 bar 中
    console.log('foo');
}

baz(); //baz调用位置
复制代码

其实,函数的调用栈也可以被想象成一个函数调用链~

绑定规则

默认绑定

独立函数调用(无法应用其他规则时,默认规则就是它了!)

看这段代码

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

var a = 1;

foo(); //2
复制代码

首先,我们需要明白一个知识点:声明在全局作用域中的变量就是全局对象的一个同名属性,本质是一个东西,不是复制得到的

当我们调用foo,this.a 被解析成 全局变量a ,调用函数应用了this的默认绑定,this指向全局对象。

不过这里有一点

虽然this的绑定规则完全取决于调用位置,但是只有 foo() 运行在 非严格模式下,默认绑定才会绑定到全局,严格模式下,与foo()的调用位置无关。

隐式绑定

考虑调用位置,是否有上下文对象。

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

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

obj.foo(); //2
复制代码

我们先来看 foo() 的声明方式,无论是直接在obj中定义还是先定义,再添加为引用属性,这个函数严格来说都不属于obj对象。

但是,调用位置会使用obj上下文来引用函数,所以,你可以说,调用obj对象时,拥有或者包含它。调用foo()时,this被绑定到obj。this.a 和 obj.a 是一样的。

对象属性引用链中,只有最后一层影响调用位置

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

var obj2 = {
    a: 42,
    foo: foo
}

var obj1 = {
    a: 2,
    obj2: obj2
}

obj1.obj2.foo(); //42
复制代码
隐式丢失
function foo() { 
    console.log( this.a );
}
var obj = { 
    a: 2,
    foo: foo 
    
};
var bar = obj.foo; // 函数别名!
var a = "oops, global"; // a 是全局对象的属性 bar(); // "oops, global"
复制代码

虽然,bar是obj.foo的一个引用,实际上,引用的是foo函数本身!所以此时 bar() 是一个不带任何修饰的函数调用。

传入回调函数
function foo(){
    console.log( this.a );
}

function doFoo(fn) {
    fn(); //调用位置
}

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

var a = "global";
doFoo( obj.foo ); //global
复制代码

参数传递其实就是一种隐式赋值,因此我们传入函数时也会被隐式赋值,所以结果和上一 个例子一样。

下篇文章将介绍:显式绑定和new绑定两种方式。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值