You Don't Know JS: Scope & Closures (附加:Lexical/dynamic作用域)(附加:Lexical-this)

JavaScript只有Lexical Scope 模式

Lexical Scope就是在写代码的时候,定义函数的时候创建的作用域!

动态作用域是在runtime时,函数被调用的地方的作用域!

实际上 dynamic Scope是 this关键字的近亲。这会在this & Object Prototypes系列讲解。

 

第二章,lexical scope是这方面的法则:Engine如何查询一个变量,在哪找到这个变量!

关键特征就是lexical scope是定义在author-time,打代码的阶段。(并不使用eval())

 

最后: this关键字关心一个函数如何被调用,这证明了this机制和动态作用域的相关性!


 


 

 

 Lexical-this

 

ES6提供了一个句法:关于函数声明的句法。arrow function. 也称fat arrow.

var foo = a => {
    console.log( a );
};

foo( 2 ); // 2

 这样就可以省略function关键字。

但是!!!你理解箭头函数中的this的绑定原则吗?

 

看这个案例:

var obj = {
    id: "awesome",
    cool: function coolFn() {
        console.log( this.id );
    }
};

var id = "not awesome";

obj.cool(); // awesome

setTimeout( obj.cool, 100 ); // not awesome  这是怎么回事???

 

👆的案例,  调用setTimeout方法的是window对象。

省略window.setTimeout(函数, 时间)的window, 那么默认this就是window.

所以,执行obj.cool。代码中的this其实是window对象。

即this是根据调用方法的对象来绑定的!!

 

解决办法是,var self = this;

在代码中预先设定好!!这就是Lexical - this,在编写代码的时候,就把this固定死!!

 

而ES6中的箭头函数,就是这个行为机制。Lexical- this。

var obj = {
    count: 0,
    cool: function coolFn() {
        if (this.count < 1) {
            setTimeout( () => { // arrow-function ftw?
                this.count++;
                console.log( "awesome?" );
            }, 100 );
        }
    }
};

obj.cool(); // awesome?

 

this不再是根据平常的调用方法的对象来绑定,而是根据Lexical-this。

 

原文: take on the this value of their immediate lexical enclosing scope

this.count中的this就是cooFn函数作用域。

箭头函数仅仅继承了 cool()函数的绑定!

cool()函数的绑定,就是obj对象!!!

 

作者使用这个方法,代替箭头函数,React中常用bind.绑定传入的prop数据。

var obj = {
    count: 0,
    cool: function coolFn() {
        if (this.count < 1) {
            setTimeout( function timer(){
                this.count++; // `this` is safe because of `bind(..)`
                console.log( "more awesome" );
            }.bind( this ), 100 ); // look, `bind()`!
        }
    }
};

obj.cool(); // more awesome

 

posted @ 2018-10-04 18:07  Mr-chen  阅读(348)  评论(0编辑  收藏  举报