相关定义

  • 引擎:从头到尾负责整个JavaScript程序的编译及执行过程。
  • 编译器:负责语法分析及代码生成等。
  • 作用域:负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。

  引擎会调用编译器对源代码进行编译,其中编译器编译过程中遇到变量声明会将其添加到当前作用域中,引擎执行编译过后的代码,遇到变量时会去作用域查找。

总结

  1. 当程序中含有var a = 2时,会分为“var a; a = 2;”两个部分:①首先是编译器查看作用域,如果作用域已含有a则忽略该声明(var a;)继续编译,否则会要求作用域在当前的集合中声明一个新的命名为a的变量(该步骤在代码执行前执行)。②编译器为引擎生成运行处理a = 2所需的代码,引擎运行该代码时会在当前的作用域集合中查看是否有a,如果有的话会使用这个变量,没有的话则会继续查找。  (ps:因为在编译执行前将变量a加入作用域中,所以即使在声明a之前调用它也不会报错,因为当前作用域中已含有它,只不过执行到赋值语句前为undefined,这也就是通常所说的声明提前。)

    1. //不会报错,因为在编译执行之前,f 函数的上级作用域中已含有变量a的声明,所以运行时会弹出undefined。
    2. window.onload = function(){
    3. function f(){
    4. alert(a);
    5. }
    6. f();
    7. var a = 0;
    8. }
  2. 引用类型:LHS和RHS,即赋值操作的左侧和右侧(也可理解为对变量赋值和使用变量的值)。因为对于引擎来说,它对于赋值和调用会对该次变量引用执行不同的操作,所以需要区分。LHS即类似a = 2,function f(a){...}中的a(被赋值),RHS即a = b + 2;console.log(b)中的b(被调用)
  3. 作用域是一层一层嵌套的,当引擎没有在当前作用域中查找到该变量时,它会向该作用域的上一层作用域继续查找,最上层为全局作用域,再没有找到则会报ReferenceError异常。如图,则会报错,因为作用域只能向上查找。
    1. //会报错,因为作用域只会向上查找
    2. window.onload = function(){
    3. function f(){
    4. var a = 0;
    5. }
    6.  
    7. alert(a);
    8. }
  4. 有一种特殊情况:在非严格模式下(无"use strict"),当变量为LHS且未声明时(即未声明就赋值),全局作用域会自动创建该变量并返回给引擎(这就是为什么在函数中不声明直接赋值,这个变量会变为全局变量),开启严格模式后则不会自动创建,报Referenct错误。如下:

    1. //当未开启严格模式时,会弹出3
    2. // "use strict";
    3. window.onload = function(){
    4. a = 3;
    5. alert(a);
    6. }

    开启(取消“use strict”注释)后,则会报错:

ps:RHS(未声明就调用)引用时会直接报错。

5. 如果找到变量对变量的值进行不合理的操作,比如试图对一个非函数类型变量进行函数调用,则会报TypeError异常。

相关例子:

  在网上搜罗了一些类似的例子,分享给大家,加深理解:

  1. //输出为number和undefined
  2. <script type="text/javascript">
  3. var a = 1;
  4. var a;
  5. alert(typeof a);
  6.  
  7. (function () {
  8. b = '-----';
  9. var b;
  10. })();
  11. alert( typeof b);
  12. </script>

  13. //输出为undefined和string
  14. <script type="text/javascript">
  15. name="aaa";
  16. function test(){
  17. alert(typeof name);
  18.  
  19. var name="bbb";
  20. alert(typeof name);
  21. }
  22. test();
  23. </script>
  24.  
  25. //输出 1,undefined,2
  1. x = 1;
  2. alert(x);
  3. var y = function() {
  4.   alert(x);
  5.   var x = 2;
  6.   alert(x);
  7. }
  8. y();
  1.  

今天就写到这里啦,感觉看完第一章作用域的讲解真的是受益匪浅,希望对你也有一定的启发~。

  

《你不知道的js》 ------1.作用域是什么的更多相关文章

  1. 你不知道的JS之作用域和闭包 附录

     原文:你不知道的js系列 A 动态作用域 动态作用域 是和 JavaScript中的词法作用域 对立的概念. 动态作用域和 JavaScript 中的另外一个机制 (this)很相似. 词法作用域是 ...

  2. 你不知道的JS之作用域和闭包(五)作用域闭包

    原文:你不知道的js系列 一个简单粗暴的定义 闭包就是即使一个函数在它所在的词法作用域外部被执行,这个函数依然可以访问这个作用域. 比如: function foo() { var a = 2; fu ...

  3. 你不知道的JS之作用域和闭包(四)(声明)提升

    原文:你不知道的js系列 先有鸡还是先有蛋? 如下代码: a = 2; var a; console.log( a ); 很多开发者可能会认为结果会输出 undefined,因为 var a 在 a ...

  4. 你不知道的JS之作用域和闭包(三)函数 vs. 块级作用域

      原文:你不知道的js系列 在第(二)节中提到的,标识符在作用域中声明,这些作用域就像是一个容器,一个嵌套一个,这个嵌套关系是在代码编写时定义的. 那么到底是什么产生了一个新的作用域,只有函数能做到 ...

  5. 你不知道的JS之作用域和闭包(二)词法作用域

    原文:你不知道的js系列 词法作用域(Lexical Scope) Lex time 一个标准的编译器的第一个阶段就是分词(token化) 词法作用域就是在词法分析时定义的作用域.换句话说,词法作用域 ...

  6. 你不知道的JS之作用域和闭包(一)什么是作用域?

    原文:你不知道的js系列 什么是作用域(Scope)? 作用域 是这样一组规则——它定义了如何存放变量,以及程序如何找到之前定义的变量. 编译器原理 JavaScript 通常被归类为动态语言或者解释 ...

  7. 翻译连载 | 第 10 章:异步的函数式(上)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

  8. 翻译连载 | 第 10 章:异步的函数式(下)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

  9. JS 函数作用域及变量提升那些事!

    虽然看了多次js函数作用域及变量提升的理论知识,但小编也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷) ...

  10. 翻译连载 | 第 11 章:融会贯通 -《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

随机推荐

  1. ASP.NET MVC---自定义HtmlHelper方法

    HtmlHelper方法是ASP.NET MVC中非常强大的特性,有了这个特性,我们就能更加随心所欲的定制自己的页面. 自定义自己的HtmlHelper方法通常有三种, 像是: 一.Razor语法 采 ...

  2. Android USER 版本与ENG 版本的差异--MTK官方解释

     分类: Android(4)  Description]Android USER 版本与ENG 版本的差异 [Keyword]USER ENG user eng 用户版本 工程版本 差异 [Solu ...

  3. VPN工作原理

    引言 在过去几十年中,世界发生了很大的变化.现在很多公司除了处理本地或地区性事务外,还要考虑全球市场和物流的问题.很多公司在全国甚至全球都设有分支机构,而这些公司都需要做的一件事情就是:找到能够与分公 ...

  4. ds18b20再硬件设计部分的注意事项

    1.DS18B20的供电方式: ps:寄生电源不是实际的电源器件,而是一种供电方式,即通过数据线供电. 如下面的两张图片所示,分别为外部供电模式下单只和多只DS18B20测温系统的典型电路连接图. ( ...

  5. jquery.elevateZoom实现仿淘宝看图片,一张小的,一张大用于鼠标经过时候显示

    实现这个效果你需要准备两张图片,一张小的,一张大用于鼠标经过时候显示.然后我们只要为img标签添加data-zoom-image属性,其值为大图的地址,最后在javascript中选择该图片调用ele ...

  6. flume-1.6.0单节点部署

    这个不多说,直接上干货,部署很简单! 步骤一:flume的下载 当然,这里也可以使用wget命令在线下载,很简单,不多说. 步骤二:flume的上传 [hadoop@djt002 flume]$ ls ...

  7. STM8建立IAR工程

    STM8是意法半导体公司出的增强型八位单片机,性能比51单片机强大,而且价格便宜,在商业应用中很受欢迎 在STM8的开发工程中主要有两种开发工具链.第一是使用IAR开发环境,第二十使用cosmic+s ...

  8. 友坚恒天.开发板(Cotex-A9 Exynos4412 开发板)

    友坚恒天.开发板 Cotex-A9 Exynos4412 开发板

  9. CSS判断不同分辨率显示不同宽度布局CSS3技术支持IE6到IE8

    CSS判断不同分辨率浏览器(显示屏幕)显示不同宽度布局CSS3技术支持IE6到IE8.将用到css3 @media样式进行判断,但IE9以下版本不支持CSS3技术,这里DIVCSS5给大家介绍通过JS ...

  10. java实现——009Fibonacci数列

    1.循环 public class T009 { public static void main(String[] args){ System.out.println(fibonacci(3)); } ...