JavaScript有函数作用域和全局作用域。
var a = 1; //a属于全局作用域
function foo()
{
var b = 0; //b属于函数作用域
}
C++语言中变量必须声明后使用,对js语言来说不是必须的。JavaScript引擎的工作方式是先解析代码,提取声明的变量。这叫做变量提升。
console.log(a); //成功打印1,因为变量提升
var a = 1;
foo(); //成功调用,因为函数名也是变量名,也会被提升。
function foo(){}
变量提升仅在当前作用域有效
function foo(){
console.log(x); //打印1,x被提升到了当前函数作用域的顶部
var x = 1;
}
console.log(x); //报错,全局作用域访问不到
和普通变量一样,函数也有自身作用域,其决定于声明时所在的作用域。
var a = 1;
var x = function () {
console.log(a); //函数当前所在作用域 a = 1
};
function f() {
var a = 2; //新的作用域 a = 2
x();
}
f() //1
阮一峰谈闭包,首先从语法入手。如何在外部获取函数内部的状态?
function foo(){
var n=999;
}
console.log(n); // error,无法获取。
//解决办法
function f1(){
var n=999;
function f2(){ //通过声明f2保存f1的内部状态,因为函数声明时有自身的作用域
console.log(n);
}
return f2; //返回,这样外部就能获取到函数内部的状态
}
闭包简单理解成"定义在一个函数内部的函数",闭包最大的特点,就是它可以“记住”诞生的环境,比如f2记住了它诞生的环境f1,所以从f2可以得到f1的内部变量。
闭包的用途:1.让变量保存在内存中 2.封装对象的私有属性和私有方法
3.回调嵌套
//用途1
function createIncrementor(start) {
return function () {
return start++;
};
}
var inc = createIncrementor(5);
inc() // 5
inc() // 6
inc() // 7
//用途2
function Person(name) {
var _age;
function setAge(n) {
_age = n;
}
function getAge() {
return _age;
}
return {
name: name,
getAge: getAge,
setAge: setAge
};
}
var p1 = Person('张三');
p1.setAge(25);
p1.getAge() // 25
//用途3
fun1(() => {
var uid = 1;
fun2(() => {
fun3(() => {
//可以访问uid
})
})
});
参考链接:http://javascript.ruanyifeng.com/grammar/function.html#toc22
Node.js开发指南 ByVoid