JavaScript 作用域(链)预解析闭包函数
Posted YuLong~W
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript 作用域(链)预解析闭包函数相关的知识,希望对你有一定的参考价值。
作用域
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突
JS作用域(ES6之前)
全局作用域
整个script标签或者是一个单独的js文件
局部作用域(函数作用域)
作用于函数内部的代码环境
注意:
JS在ES6之前没有块级作用域:块作用域由 { } 包括,比如 if { } ; for { } 。因此 if 和 for 中定义的变量在外侧可以随意使用
变量的作用域
- 全局变量:在函数外部定义的变量(显示定义)或在内部不用var定义,直接赋值的变量(隐式定义) 在浏览器页面关闭后才销毁,比较占内存资源空间
- 局部变量:在函数内部用var定义的变量或函数的形参 函数调用结束后就销毁,节省内存资源
- 块级变量:ES6中使用let关键字在语句块中定义的变量 当语句块结束就销毁,更节省内存空间
作用域链
在一个函数内部声明另一个函数时,内层函数只能在外层函数作用域内执行,在内层函数执行过程中,若引入某个变量,先在当前作用域中寻找,若未找到,则继续向上一层级作用域中寻找,直到全局作用域,即采用链式查找。
采取就近原则的方式来查找变量最终的值。
var num=10;
function fn(){
var num=20
function fun(){
console.log(num) //输出结果为:20
}
fun()
}
fn()
预解析
javascript 代码是由浏览器中的 JavaScript 解析器来执行的。
JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行。
预解析: 在当前作用域下, JS 代码执行之前,浏览器会默认把带有 var 和 function 声明的变量在内存中进行提前声明或者定义。
代码执行: 从上到下依次执行
变量预解析
变量预解析也称变量提升:变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升
console.log(num) //执行结果为:undefined
var num=10
//以上两行相当于执行以下代码
var num
console.log(num)
num=10
fun()
var fun=function(){
console.log(22) //执行报错:fun is not a function
}
//相当于执行以下代码
var fun
fun()
fun=function(){
console.log(22)
}
//函数表达式 调用必须写在函数表达式下面
函数预解析
函数预解析也称函数提升:函数的声明会被提升到当前作用域的最上面,但是不调用函数
fn()
function fn(){
console.log(11) //执行结果为:11
}
预解析综合案例
var num=10
fun()
function fun() {
console.log(num)
var num=20
}
//相当于执行以下代码
var num
function fun(){
var num
console.log(num) //根据作用域链就近原则,输出结果为undefined
num=20
}
num=10
f1()
console.log(c)
console.log(b)
console.log(a)
function f1() {
var a = b = c = 9 //与var a=9,b=9,c=9 集体声明不同
console.log(a)
console.log(b)
console.log(c)
}
//相当于执行以下代码
function f1() {
var a
a=b=c=9
// b和c直接赋值,没有var声明,相当于 全局变量
console.log(a) //输出结果:9
console.log(b) //9
console.log(c) //9
}
f1()
console.log(c) //9
console.log(b) //9
console.log(a) //报错:a is not defined
闭包函数
有权访问另一函数作用域内变量(局部变量)的函数
function fn() {
var times=0
var c=function(){
return ++times
}
return c
}
//js中对闭包的语法规范
//在函数外部访问函数内部的变量
var count=fn()
//js解析器使得times不再初始化,给它一个空间存储
console.log(fn)
console.log(fn())
console.log(count())
console.log(count())
console.log(count())
两点用途:
- 在函数外部读取函数内部的变量
- 让变量的值始终保持在内存中
注意:由于闭包会使得函数中变量一直被保存在内存中,内存消耗很大,所以闭包的滥用可能会降低程序的处理速度,造成内存损耗等问题
以上是关于JavaScript 作用域(链)预解析闭包函数的主要内容,如果未能解决你的问题,请参考以下文章