作用域闭包四五章及附录

本文深入探讨JavaScript中的提升与闭包概念,解析变量与函数声明如何在编译阶段被处理,以及闭包如何让函数记住其词法作用域。通过具体示例讲解循环加闭包的常见陷阱及解决方案,同时介绍模块模式与现代模块的实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第四章:提升

-先有鸡(赋值)还是先有蛋(声明)

 

编译器再次袭来

-代码的任何部分被执行之前,所有的声明,变量和函数都会首先被处理

-变量和函数声明从代码流中出现的位置”移动”到代码的顶端(提升)

-先有蛋(声明)后有鸡(赋值)

-提升以作用域为单位

-函数表达式不会被提升

 

函数优先

-函数首先被提升然后才是变量

-普通块内部出现的函数声明一般会被提升至外围的作用域

-不可靠,避免在块中声明函数

 

复习

-var a = 2;JavaScript引擎将var a(编译期任务)和a = 2(执行时任务)分离处理

 

第五章:作用域闭包

 

启蒙

-在JavaScript中闭包无处不在,你只是必须认出它并接纳它

 

事实真相

-闭包定义

       函数能够记住并访问它的词法作用域,即使当这个函数在它的词法作用域之外执行时

-子函数拥有一个词法作用域闭包覆盖着父函数的内部作用域

       1.父函数被执行之后,子函数依然拥有对那个作用域的引用,这个引用称为闭包

       2.子函数在它被编写的词法作用域之外被调用,闭包使之可以访问编写时被定义的词法作用域

-函数可以被作为值传递

-计时器、事件处理器、Ajax请求、跨窗口消息、web worker、或者任何其他的异步(或同步!)任务,当你传入一个 回调函数,你就在它周围悬挂了一些闭包!

 

循环+闭包

-超时的回调函数都将在循环完成之后立即运行

for (var i=1; i<=5; i++) {

        setTimeout( functiontimer(){

                 console.log( i );

        }, i*1000 );

}

-你会得到“6”被打印5次,一秒一个

for (var i=1; i<=5; i++) {
        (function(j){
                 setTimeout( functiontimer(){
                         console.log( j );
                 }, j*1000 );
        })( i );
}

-用IIFE函数为每次迭代时闭包一个新的作用域

-会打印1-5,一秒一个
 

重温块儿作用域

-let劫持一个块变成我们可以闭包的作用域
for (var i=1; i<=5; i++) {
        let j = i; // 呀,给闭包的块儿作用域!
        setTimeout( functiontimer(){
                 console.log( j );
        }, j*1000 );
}
-let在循环头,这个变量将不只是为循环声明一次,而是为每次迭代声明一次,并且在每次后续的迭代中被上一次迭代末尾值初始化
for (let i=1; i<=5; i++) {
        setTimeout( functiontimer(){
                 console.log( i );
        }, i*1000 );
}
-块儿作用域和闭包携手工作,解决世界上所有问题
 

模块

-揭示模块:实现模块模式最常见的方法
-行使模块模式两个“必要条件”
	1.必须有一个外部的外围函数,且至少被调用一次(每次创建一个新的模块实例)
	2.外围函数必须至少返回一个内部函数,并且可以访问/修改这个私有状态
-在模块实例内部持有一个指向公用API对象的内部引用,可以从内部修改模块
 

现代的模块

-调用一个函数定义包装器,并将它的返回值作为这个模块的API保存下来
 

未来的模块

-ES6为模块的概念增加了头等的语法支持
-当通过模块系统加载时,ES6将一个文件视为一个独立的模块
-ES6模块没有“内联”格式,它们必须被定义在一个分离的文件中(每个模块一个)
-import导入一个模块的API的一个或多个成员
-export为当前模块的公用API导出一个标识符(变量/函数)
 

复习

-我们如何在函数即是值,而且可以被随意传递的词法作用域环境中编写代码
-感觉像JAVA中在一个类中定义方法,在其他地方导包后就可以调用方法
 

附录A:动态作用域

-不沿着嵌套的词法作用域链往上走一层,而是沿着调用栈向上走
-JavaScript实际上没有动态作用域,this机制有些像动态作用域
-关键差异
-词法作用域:编写时的,关心函数在何处被声明
-动态作用域(和this):运行时的,关心函数从何处被调用
 

附录B:填补块儿作用域

-ES6中let在前ES6可用catch块转换
-Traceur:Google维护的将ES6转译为前ES6代码
-隐含的和明确的块儿
	使用更好和更明确的let语句形式,即使它还不是任何ES官方版本的一部分
-性能:使用块儿作用域,使用合理的工具
 

附录C:词法this

-var self = this免除了理解和正确使用this绑定的整个问题
-简单解释:摒弃了this绑定的所有一般规则,将它们的立即外围词法作用域作为this的值
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值