正经文章的地方

从词法作用域理解问题

一、词法作用域

词法作用域的概念:当前区块查找变量的范围。

静态的词法作用域主要是指在定义函数的时候,函数本身的词法作用域已经被决定,在普通调用函数执行时,不会因为实际调用的位置去更改作用域。

var value = 1;

function foo() {        // 在这里定义函数的时候,value就已经决定了作用域
    console.log(value); // 由于value在foo中无定义,自动向上查找
}                       // 上层作用域:全局变量value = 1

function bar() {
    var value = 2;
    foo();              // 调用时不变更作用域,依然输出window.value
}

bar();                  // 1

二、闭包

在定义函数的词法作用域以外的其他作用于调用函数,且该函数持有定义作用域的变量引用,导致定义作用域无法被自动回收、销毁。

example:

我外出上班不在家,但是我把需要的档案放家里了,导致我妈没法把档案用完了就丢掉,因为不知道不在家的我什么时候有需求要用一下。

此处我是函数,家是定义作用域,文档是被引用的定义作用域内的变量,我上班的地点是实际使用时的作用域。

三、apply call

在指定词法作用域调用指定函数。

example:

有一个公用的测量面具工具, 会根据当前房间属性输出面积和使用报价。将该工具拿到指定房间使用,就会输出对应的数值。

此处工具就是被调用的A函数,当前房间就是目标this,即使用时的词法作用域,依赖的报价器作为参数传递进入工具函数,并且使用相同的词法作用域(当前房间)。

A.apply(B, [arg1, arg2, arg3, … , argN])
A.call(B, arg1, arg2, arg3, … ,argN)
传参不同。

// 定义一个测量面积并且报价的工具,依赖一个报价器
var showMeArea = function (getMoney) {
    console.log(`${this.place}面积为${this.area}㎡,请支付${getMoney(this.area)}`);
}

// 被依赖的报价器
var getMoney = function(area) {
    return area * 2;
}

// 实际需要使用工具的房间
var roomA = {
    place: '305',
    area: 30
}

// 使用
showMeArea.apply(roomA, [getMoney]);
showMeArea.call(roomA, getMoney);

四、 模块

用一个包装函数封装一个私有作用域,只对外暴露API函数,这些暴露的API函数通过闭包来影响模块内部的变量,保证内部变量的安全性。