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 代码执行之前,浏览器会默认把带有 varfunction 声明的变量在内存中进行提前声明或者定义
代码执行: 从上到下依次执行

变量预解析

变量预解析也称变量提升:变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升

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 作用域(链)预解析闭包函数的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript函数函数进阶作用域及预解析

JavaScript-变量的作用域闭包预解析

JavaScript必须了解的知识点总结。

JavaScript必须了解的知识点总结。

javascript的作用域链变量提升及预解析

javascript的作用域链变量提升及预解析