This 和 执行上下文环境的理解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/smalCat/article/details/82107587

/*
        在没有看《你不知道的JavaScript》这个系列的书之前,
 我如大多数前端开发同伴一样,如常识般的认为this指向对象本身,或者指向对象的作用域。
    
        实际呢,this是 上下文执行环境中的一个属性,this的指向也不是如常识一般指向谁谁,
 而是依据调用栈和执行位置决定的(或者说执行环境),并且 this 是在运行时绑定的,并不是在编写时绑定。

  this指向什么完全取决于函数在哪里被调用。

引用书中一段code:

    function foo () {
        var a = 2;
        this.bar();
    }

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

    foo(); // a is not defined;

解析:
    1、对foo函数进行声明提升,执行foo();

    2、对 a、bar进行变量提升,bar在前,a在后,因为bar是函数,调入栈中,在队列中第一执行。

    3、搜索引擎进行LSH查询,找到a,然后进行 a = 2;赋值操作。

    4、this,这个this指向谁,依据调用栈: 全局 -> foo(),调用位置是: 全局,
        判断,此时this指向全局,调用 bar().

    5、执行bar(),依据调用栈: 全局 -> bar(),调用位置是: 向全局,判断,此时this指向全局,
        执行this.a,引擎进行LSH查询,
        在宽松模式下,全局执行环境没有找到 a 这个参数,会自动创建一个a,然而a是没有值的。
        (在严格模式下,全局执行环境是不会创建 a 变量,所以会抛出不一样的错误)    

    6、执行 console.log(),因为this执行环境中a没有赋值,此时抛出错误, a 没有定义。

    7、a在哪里呢,a在foo()的作用域中,而bar调用a,明显跨域,依据闭包原理,bar是访问不到foo内部的
        a的,如果要访问到a,则需要显示传入参数,调用a的作用域.
    
    8、对这段代码我突然想进行尝试操作,所以我写了如下代码:

        function foo () {
            var a = 2;
            this.bar();
        }

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

	    foo();

    // 理想很丰满,现实是很骨感的,此时在bar 中 左边的this是无效的。所以你懂得。

*/

注意:书写函数时,应尽量书写具名函数,以方便需要用到自身的时候进行回调,如果是匿名函数,则会因为没有指向函数对象的词法标识符,而无法 找到自身,从而无法调用。

老式解决办法,使用伪数组arguments.callee引用当前对象本身,不过在现在的JavaScript的环境下,它已经被弃用了。

 依据函数调用位置确定this指向。

this指向是可以通过固定this来修复的,这里我们称为 显式绑定 也称 硬绑定,可以使用的方法由call、apply、new,以下贴出他们的优先级顺序,以及显式绑定后的this指向:

例外就是,当你使用call和apply进行显示绑定是,如果传入的this对象是为undefind、null这些的时候,因为没有this指向,

所以无法重新绑定,这里就默认进行隐式绑定,即绑定到全局,this指向全局,同时也可以在bind(...)中对绑定函数的参数进行柯里化(预先对参数赋值),为了不造成三方库或者模块的this污染全局,或者内部this指向错乱,更安全的this绑定空对象的写法为:

        

function foo (a,b) {
    console.log(a, b);
    return a + b;
}

var K = Object.create(null);

foo.apply(K, [5,6]); // a:5,b:6

var bar = foo.bind(K, 3) //柯里化 a = 3;

bar(9); // a:3,b:9

console.log(bar(9)); // 12



这里说一下箭头函数的this指向的理解:
    
    箭头函数的this来自于外部的执行上下文环境的this,外部执行上下文环境依然是在引擎运行时绑定的,那么我依然认为箭头函数的this是在调用外部执行上下文环境时绑定的,依然是在运行时绑定的,而不是在编写时就绑定了。

this指向为调用位置,固定绑定this为空,则指向全局。核心思想,

猜你喜欢

转载自blog.csdn.net/smalCat/article/details/82107587
今日推荐