cover

三部曲的简介

本篇文章,是介绍JavaScript中作用域部分。 自己这段时间也算是看了很多JavaScript的书,都是和作用域方面有关的。 ES6那是后话,暂时不提。这儿是ES5的情况。
考虑到内容过多。准备分为三部分来讲述。 分别是:块级作用域、IIFE与ES6 let、闭包。

第一篇文章,讲的就是块级作用域的内容。

什么是块级作用域?

在C语言,Java中,都有块级作用域的概念。举个最经典的例子。

for (int i = 0; i < count; ++i)  
{
  /* 这是C语言 */
}
printf("%d\n",i ); //出错,读取不到i的值  

在循环结束后,变量i就不复存在。这就是块级作用域,变量只能在函数、循环运行是存在。一旦函数或循环运行完毕,变量就会被销毁。

原理

块级作用域的原理,是我看《大话数据结构》这本书中学习到的。 栈是一种LIFO的结构。先进后出。 以刚才的循环为例。 在运行for的时候,压栈,把for循环和对应的变量i压入栈内存。运行结束时便将栈内存弹出。里面的变量i也不复存在了。

为什么要有块级作用域

打个比方,如果一个项目有一百个人在同时开发。每个人都写了好几个循环。 如果没有块级作用域,那么在最后项目合并时候,将会有数不清的变量名冲突。比如说,100个i? 这种块级作用域中定义变量的方式,叫做局部变量。

JavaScript中的块级作用域

在JavaScript中,存在一个全局变量环境。但JavaScript的块级作用域是不完整的。 它可以有局部变量。像这样的。

function test() {  
  var i = 0;
  console.log(i)
}

test();// 0  
console.log(i);// error,i未被定义  

这是局部变量的概念。其实非常好理解。 这个用var定义的变量。只有在函数执行的瞬间才存在,执行完毕就会被销毁。 如果不用var。直接

function test() {  
  i = 0;
  console.log(i)
}

test();// i = 0  
console.log(i);// i = 0  

因为在函数内不用var关键字定义的变量,在函数运行后会成为全局变量。

而JavaScript没有块级作用域所暴露的问题,在循环就有体现。 假如在JavaScript运行一个for循环

for (var i = 0; i < 10; i++) {  
  //一些操作
}
console.log(i) // i = 10  

你会发现i还会存在。此时的i,是在全局变量环境中的。 这是极其恐怖的事情,因为在当代的前端开发中,大型项目往往有很多人一起开发。但是全局变量环境只有一个。 那么也就是说,如果这样的话,项目中变量的冲突会极其严重。

那怎么解决?

这就是下一章要讲述的内容啦,会讲述JavaScript如何模仿块级作用域,同时也会讲述ES6原生实现的块级作用域。

扫描二维码,分享此文章

Lxxyx's Picture
Lxxyx