词法作用域
作用域是一套根据标识符名称查找变量的规则。javascript采用词法作用域的语言。词法作用域是指变量和函数声明的作用域是由书写代码时的位置决定的。
变量作用域
变量分为全局变量和局部变量。 全局变量拥有全局作用域,在js代码中任何地方都是可见的。局部变量:在函数中定义的变量只在函数体内及其所嵌套的函数体内是可见的。
函数作用域
javascript没有块级作用域,取而代之的是函数作用域,变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是可见的。
将变量理解为某个对象的属性
全局变量是全局对象的属性。对于局部变量而言并没有此规定。但我们可以理解为,局部变量当作跟函数调用相关的某个对象的属性,称这个对象为变量对象。
理解变量作用域链
每段JavaScript代码都有一个与之关联的作用域链,这个作用域链是一个对象列表,这组对象定义了这段代码能够访问的变量和函数。
标识符解析是沿着作用域链一级一级地搜索标识符的过程。搜索过程始终从作用域链的前端开始, 然后逐级地向后回溯,直至找到标识符为止
var color = "blue";
function changeColor(){
var anotherColor = "red";
function swapColors(){
var tempColor = anotherColor;
anotherColor = color;
color = tempColor;
// 这里可以访问 color、anotherColor 和 tempColor
}
// 这里可以访问 color 和 anotherColor,但不能访问 tempColor
swapColors();
}
// 这里只能访问 color
changeColor();
console.log(color)
对于最顶层的代码,作用域链是一个全局对象组成。 对于没有嵌套的函数,作用域链是函数参数和局部变量的对象和全局对象组成; 对于嵌套函数,作用域链是嵌套函数的参数和局部变量的对象,包含函数的参数和局部变量的对象,全局对象
闭包是什么
- 闭包就是「函数」和「函数内部能访问到的变量」的总和
- 闭包就是能够读取其他函数内部变量的函数。
- 闭包是指有权访问另一个函数作用域中的变量的函数。
- 闭包就是指当函数可以记住并访问所在的词法作用域,并且保持着对词法作用域的引用,即使函数是在当前作用域之外执行。
闭包的本质
JavaScript 闭包的本质源自两点,词法作用域和函数当作值传递。 词法作用域,就是,按照代码书写时的样子,内部函数可以访问函数外面的变量。 函数被当作值返回时,依然保持着对其词法作用域的引用。
闭包的特点
闭包常常用来「间接访问一个变量」。换句话说,「隐藏一个变量」。
闭包让你可以在一个内层函数中访问到其外层函数的作用域。
可以避免使用全局变量,防止全局变量污染;
闭包的创建
闭包就是可以创建一个独立的环境,每个闭包里面的环境都是独立的,互不干扰。
每次外部函数执行的时候,外部函数的引用地址不同,都会重新创建一个新的地址。
闭包找到的是同一地址中父级函数中对应变量最终的值。
//立即执行函数形式的闭包
!function(){
var lives = 50
window.奖励一条命 = function(){
lives += 1
}
window.死一条命 = function(){
lives -= 1
}
}()
//嵌套函数形式的闭包
function funA(){
var a = 10; // funA的活动对象之中;
return function(){ //匿名函数的活动对象;
alert(a);
}
}
var b = funA();
b(); //10
function outerFn(){
var i = 0;
function innerFn(){
i++;
console.log(i);
}
return innerFn;
}
var inner = outerFn(); //每次外部函数执行的时候,都会开辟一块内存空间,外部函数的地址不同,都会重新创建一个新的地址
inner();
inner();
inner();
var inner2 = outerFn();
inner2();
inner2();
inner2();//1 2 3 1 2 3