递归和闭包
- 递归是通过函数名调用自己
- 闭包是能够读取其他函数内部变量的函数
作用域:
- Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。另一方面,在函数外部自然无法读取函数内的局部变量。这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!
function f1(){
var n=999;
function f2(){
alert(n); // 999
}
return f2;
}
var result=f1();
result(); // 999
- 我不能再f1外面调用f1的局部变量,但是生命在f1里面的f2可以调用他的上一级也就是f1的局部变量
- 于是让f1返回f2,从而得到f1的局部变量
- 这里闭包起到的作用是读取函数内部的变量
自执行函数
声明函数的方式:
// 声明函数fun0
function fun0(){
console.log("fun0");
}
//执行函数fun0
fun0(); // fun0
// 声明函数fun1 - 变量方式
var fun1 = function(){
console.log("fun1");
}
// 执行函数fun1
fun1(); // fun1
加上()得以在声明的时候同时执行函数:
(function fun0(){/*代码段*/})();
计数器:
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
add();
add();
add();
- add是一个变量
- 自调用函数在声明的同时执行,counter初始化为0,然后
return function () {return counter += 1;}
- 变量add接收了return的内容,相当于变量方式声明了函数add
- 之后调用add()只是+1
- 函数add访问了它父作用域中的变量counter,因此add是一个闭包
- 自调用函数已经关闭了,add还可以访问counter变量,这里闭包起到的作用是让某个变量的值始终保持在内存中
- 所以闭包使得函数中的变量都被保存在了内存中,内存消耗很大
在之前的JS中,没有专门为模块化提供相应的语法支持,但可以借助闭包中调用自执行函数的方式来模拟一个模块
模块
ES6标准发布后,module成为标准,标准使用是以export指令导出接口,以import引入模块,但是在我们一贯的node模块中,我们依然采用的是CommonJS规范,使用require引入模块,使用module.exports导出接口。
import后面的from指定模块文件的位置,可以是相对路径,也可以是绝对路径,.js后缀可以省略。如果只是模块名,不带有路径,那么必须有配置文件,告诉 JavaScript 引擎该模块的位置。某些打包工具可以允许或要求使用扩展名。
export 命名导出需要export 名字和import名字严格一致。而export default命令,为模块指定默认输出,在import 的时候可以随意命名名字。
- 通过export方式导出,在导入的时候需要加{},export default不需要在导入的时候加{}
- 在一个文件或者模块中,export,import可以有多个,但是export default只能有一个