前段时间学了下JavaScript作用域,这个东西在JavaScript非常重要,也是JavaScript很基础的东西,正如少林里面基础武功,有了基础,才能学绝世武功。

  作用域的作用是啥?一套设计良好的规则来存储变量,并且之后可以方便的找到这些变量。

  就JavaScript里面的作用域来说,我总结有这么几个关键词:

  1. 词法作用域

  2. 函数作用域

  3. 块级作用域

  4. 闭包

  5. 提升

  好吧,我脑海里面能想到的就这么多了,不够的,也可以有朋友指出来,接下来,我一个一个过下这些词。

  一、词法作用域

  顾名思义,针对于词法的作用域,这是什么鬼?词法有作用域吗?难道不是只有函数作用域吗?有啥子用啊?  

  其实,词法作用域非常有用,它是针对词法的,没错就是词法,那什么是词法?

  JavaScript是一面动态语言,也就是先编译,再运行,在编译的第一个工作阶段叫词法化。词法化的时候,会对源代码中的标识符(变量和函数)进行检查,如果有状态的解析过程,还会赋予单词语意。

  词法作用域就是定义在词法阶段的作用域,词法作用域是有你在写代码时将变量和块作用域写在哪里来决定的。

  引擎凭什么能找到变量?是根据什么来查找的呢?

  举个例子:

function test() {
var a = 3;
console.log(a);
} test(); // output 3;

  这个例子相当简单,就拿这个a变量来说,test函数内,是局部变量,a的词法作用域就是test函数体内,如果在函数体外再调用a变量,比如:

function test() {
var a = 3;
console.log(a);
} test(); cosole.log(a);

  会抛出引用异常的错误(ReferenceError)。

  通过上面这个例子,只是简单的说明了下变量的词法作用域。在词法分析中,任何标识符,都有词法作用域,引擎就通过作用域来查找标识符的,会从内到外层作用域查找,直到找到第一个匹配的标识符停止,如果没找到,这会抛出引用异常的错误。

  二、函数作用域

  函数作用域,相信学过编程语言(比如C、C++等),对这个应该不陌生,每个函数都有自己的作用域,也就是函数作用域,这里就跳过了。

  三、块级作用域

  什么是块级作用域?块级作用域,就是用一对{}包裹起来的作用域,比如if语句,else语句,还有for语句等等。但是一般来说JavaScript里面是没有块级作用域这个概念的,但是,也有特例,在es3中开始,就有一个块级作用域的例子。

  就是try catch,看下面例子:

try	{
undefined(); // 强行出错
} catch(e) {
console.log(e);
}

  如果没有块级作用域的概念,那么这个e应该是全局的,在外面也可以访问,如下:

try	{
undefined(); // 强行出错
} catch(e) {
console.log(e);
} console.log(e);

  实际上,这样会抛出引用异常,e变量仅在catch中有效,这说明try catch是支持块级作用域的。

  其实在ES6中,JavaScript已经可以支持块级作用域了,比如let关键字。

  四、闭包

  闭包是什么?闭包和函数有什么关系?

  其实闭包我们平时很常用,只是大家没注意到罢了,闭包是函数运行时能访问其函数作用域之外的上下文环境,是一个动态的概念。如下:

function test() {

	var a = 3;

	function btest() {
// a变量为btest函数之外的变量
console.log(a);
} btest(); // 通过闭包调用a
} test();

  闭包是函数的代码在运行过程中的一个动态环境,函数可以理解为静态的代码。在这个动态环境内,如果函数只访问函数作用域里面变量(当然全局变量也算),那么是不存在闭包的;但是这个动态环境,还能访问其函数作用外的其他变量(也除了全局变量),那么有闭包了。

  五、提升

  提升什么?其实呢,就是浏览器在预编译的时候,会把所有的声明提前,其中包括变量声明和函数声明,如下:

test();

function test() {

	var a = 3;

	console.log(a);
}

  上面的代码演示,就是函数提升,注意,函数表达式不会提升,如下:

test();

var tset = function() {

	var a = 3;

	console.log(a);
}

  这会抛出引用异常的错误!

a = 3;

var a;

console.log(a);

  上面的代码是变量声明提升,切记是声明提升,赋值操作并不提升。

  总结:JavaScript使用作用域链来实现闭包,作用域链由执行环境维护,JavaScript中所有的标识符都是通过作用域链来查找值的。

  作用域这块,现在已经入门了,离精通还差很多,还需要多学多练,早日把这块搞透,学习正如逆水行舟,真是因为难,才更需要搞懂,如果只做力所能及的事,将永远得不到提升!

浅谈JavaScript的作用域的更多相关文章

  1. 浅谈JavaScript 函数作用域当中的“提升”现象

    在JavaScript当中,定义变量通过var操作符+变量名.但是不加 var 操作符,直接赋值也是可以的. 例如 : message = "hello JavaScript ! " ...

  2. 浅谈javascript函数节流

    浅谈javascript函数节流 什么是函数节流? 函数节流简单的来说就是不想让该函数在很短的时间内连续被调用,比如我们最常见的是窗口缩放的时候,经常会执行一些其他的操作函数,比如发一个ajax请求等 ...

  3. 浅谈JavaScript中的闭包

    浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...

  4. 浅谈 JavaScript 编程语言的编码规范

    对于熟悉 C/C++ 或 Java 语言的工程师来说,JavaScript 显得灵活,简单易懂,对代码的格式的要求也相对松散.很容易学习,并运用到自己的代码中.也正因为这样,JavaScript 的编 ...

  5. 浅谈JavaScript浮点数及其运算

    原文:浅谈JavaScript浮点数及其运算     JavaScript 只有一种数字类型 Number,而且在Javascript中所有的数字都是以IEEE-754标准格式表示的.浮点数的精度问题 ...

  6. 浅谈 js eval作用域

    原文:浅谈 js eval作用域 就简单聊下如何全局 eval 一个代码. var x = 1; (function () { eval('var x = 123;'); })(); console. ...

  7. 浅谈javascript的原型及原型链

    浅谈javascript的原型及原型链 这里,我们列出原型的几个概念,如下: prototype属性 [[prototype]] __proto__ prototype属性 只要创建了一个函数,就会为 ...

  8. 浅谈JavaScript中的null和undefined

    浅谈JavaScript中的null和undefined null null是JavaScript中的关键字,表示一个特殊值,常用来描述"空值". 对null进行typeof类型运 ...

  9. 浅谈JavaScript中的正则表达式(适用初学者观看)

    浅谈JavaScript中的正则表达式 1.什么是正则表达式(RegExp)? 官方定义: 正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则就是这个模具,定义一种规则去 ...

随机推荐

  1. 20169212《Linux内核原理与分析》第十一周作业

    缓冲区溢出漏洞实验 缓冲区溢出漏洞:缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况.这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段.这一漏洞的出现是由于数据缓冲器 ...

  2. 学习记录之APPCan

    2015年5月28的笔记,整理笔记搬了过来,好坏是自己当时的小成果,以后有想法继续补充 APPCan移动开发服务平台,有内置模板,列表样式,主页样式等供选择,适合开发简单布局或与内置模板布局相同的项目 ...

  3. 【原创】MVC4+Jquery+EasyUI实现的工作流平台

    最近把工作流从传统的WebFrom上迁移到我的MVC4安全权限基础框架中,感觉非常不错MVC4在各方面给用户的体验确实跟以前传统的WEB是质的提升.由于后面要做基于工作流技术的ERP,所以需要先把工作 ...

  4. Oracle逻辑备份与恢复

      1. 备份的类型 按照备份方式的不同,可以把备份分为两类: 1.1 逻辑备份:指通过逻辑导出对数据进行备份.将数据库中的用户对象导出到一个二进制文件中,逻辑备份使用导入导出工具:EXPDP/IMP ...

  5. [CentOS] 解决 crontab 无法读取环境变量的问题

    参考资料:http://blog.slogra.com/post-238.html 1. 问题描述 一段数据处理的 shell 程序,在 shell 中手动运行,可以正确执行.但是,把它放在 cron ...

  6. sphinx全文检索功能 | windows下测试 (一)

    前一阵子尝试使用了一下Sphinx,一个能够被各种语言(PHP/Python/Ruby/etc)方便调用的全文检索系统.网上的资料大多是在linux环境下的安装使用,当然,作为生产环境很有必要部署在* ...

  7. 用C#实现的内存映射

    当文件过大时,无法一次性载入内存时,就需要分次,分段的载入文件 主要是用了以下的WinAPI LPVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD ...

  8. web app性能大讨论

    1.Application:应用,为用户完成一个或多个功能而设计的程序: 2.Internet or Intranet:运行于广域网或局域网之上: 3.Browser-supported langua ...

  9. spout详解

    spout放在每个executer执行,我们先从spoutExecutors的初始化开始往下看,spoutExecutors是在一个worker中管理其中的tasks,在SpoutExecutors的 ...

  10. tpch-kudu

    1.在impala里建立好文本表: create external table customer (C_CUSTKEY INT, C_NAME STRING, C_ADDRESS STRING, C_ ...