你不知道的JavaScript 二
词法作用域
上次说到作用域,将其定义为一套规则,这套规则用来管理引擎如何在当前作用 域以及嵌套的子作用域中根据标识符名称进行变量查找。
作用域共有两种主要的工作模型。第一种是最为普遍的,被大多数编程语言所采用的词法作用域。另外一种叫作动态作用域,仍有一些编
程语 言在使用(比如 Bash 脚本、Perl 中的一些模式等)。
大部分标准语言编译器的第一个工作阶段叫作词法化(也叫单词化)。词法化的过程会对源代码中的字符进行检查,如果是有状态的解析过
程,还会赋予单词语义。
那么什么是词法作用域 ?
词法作用域就是定义在词法阶段的作用域。换句话说,词法作用域是由你在写 代码时将变量和块作用域写在哪里来决定的,因此当词法分析
器处理代码时会保持作用域不变 。
查找
作用域查找会在找到第一个匹配的标识符时停止。在多层的嵌套作用域中可以定义同名的 标识符,这叫作“遮蔽效应”(内部的标识符“遮蔽”
了外部的标识符)。抛开遮蔽效应, 作用域查找始终从运行时所处的最内部作用域开始,逐级向外或者说向上进行,直到遇见 第一个匹配的标
识符为止。
1.全局变量会自动成为全局对象(比如浏览器中的 window 对象)的属性,因此 可以不直接通过全局对象的词法名称,而是间接地通过对全局
对象属性的引 用来对其进行访问。
window.a
通过这种技术可以访问那些被同名变量所遮蔽的全局变量。但非全局的变量 如果被遮蔽了,无论如何都无法被访问到。
2.无论函数在哪里被调用,也无论它如何被调用,它的词法作用域都只由函数被声明时所处 的位置决定。
3.词法作用域查找只会查找一级标识符 。
小结:
词法作用域意味着作用域是由书写代码时函数声明的位置来决定的。编译的词法分析阶段基本能够知道全部标识符在哪里以及是如何声明的,
从而能够预测在执行过程中如何对它们进行查找。
欺骗词法
JavaScript 中有两个机制可以“欺骗”词法作用域:eval(..) 和 with。前者可以对一段包含一个或多个声明的“代码”字符串进行演算,并借此
来修改已经存在的词法作用域(在 运行时)。后者本质上是通过将一个对象的引用当作作用域来处理,将对象的属性当作作用域中的标识符来
处理,从而创建了一个新的词法作用域(同样是在运行时)。
JavaScript中 还 有 其 他 一 些 功 能 效 果 和eval(..)很 相 似。setTimeout(..)和 setInterval(..) 的第一个参数可以是字符串,字符串
的内容可以被解释为一段动态生成的 函数代码。这些功能已经过时且并不被提倡。不要使用它们!
new Function(..) 函数的行为也很类似,最后一个参数可以接受代码字符串,并将其转 化为动态生成的函数(前面的参数是这个新生成的函数
的形参)。这种构建函数的语法比 eval(..) 略微安全一些,但也要尽量避免使用。
with 通常被当作重复引用同一个对象中的多个属性的快捷方式,可以不需要重复引用对象本身。with 可以将一个没有或有多个属性的对象处
理为一个完全隔离的词法作用域,因此这个对 象的属性也会被处理为定义在这个作用域中的词法标识符。
尽管 with 块可以将一个对象处理为词法作用域,但是这个块内部正常的 var 声明并不会被限制在这个块的作用域中,而是被添加到 with 所处
的函数作用域中。
eval(..) 函数如果接受了含有一个或多个声明的代码,就会修改其所处的词法作用域,而 with 声明实际上是根据你传递给它的对象凭空创建了
一个全新的词法作用域。
eval(..) 和 with的副作用是引擎无法在编译时对作用域查找进行优化,因为引擎只能谨慎地认为这样的优化是无效的。使用这其中任何一个机制
都将导致代码运行变慢。不要使用它们。
你不知道的JavaScript 二的更多相关文章
- 《你不知道的JavaScript》整理(二)——this
最近在读一本进阶的JavaScript的书<你不知道的JavaScript(上卷)>,这次研究了一下“this”. 当一个函数被调用时,会创建一个活动记录(执行上下文). 这个记录会包含函 ...
- 读《你不知道的JavaScript(上卷)》后感-作用域闭包(二)
github原文 一. 序言 最近我在读一本书:<你不知道的JavaScript>,这书分为上中卷,内容非常丰富,认真细读,能学到非常多JavaScript的知识点,希望广大的前端同胞们, ...
- JS闭包—你不知道的JavaScript上卷读书笔记(二)
关于闭包,初学者会被绕的晕头转向,在学习的路上也付出了很多精力来理解. 让我们一起来揭开闭包神秘的面纱. 闭包晦涩的定义 看过很多关于闭包的定义,很多讲的云里雾里,晦涩难懂.让不少人以为闭包是多么玄乎 ...
- 《你不知道的JavaScript》整理(一)——作用域、提升与闭包
最近在读一本进阶的JavaScript的书<你不知道的JavaScript(上卷)>,里面分析了很多基础性的概念. 可以更全面深入的理解JavaScript深层面的知识点. 一.函数作用域 ...
- 读书笔记-你不知道的JavaScript(上)
本文首发在我的个人博客:http://muyunyun.cn/ <你不知道的JavaScript>系列丛书给出了很多颠覆以往对JavaScript认知的点, 读完上卷,受益匪浅,于是对其精 ...
- JavaScript中的this(你不知道的JavaScript)
JavaScript中的this,刚接触JavaScript时大家都在大肆渲染说其多么多么的灵巧重要,然而自己并不关心:随着自己对JavaScript一步步深入了解,突然恍然大悟,原来它真的很重要!所 ...
- 读《你不知道的JavaScript(上卷)》后感-浅谈JavaScript作用域(一)
原文 一. 序言 最近我在读一本书:<你不知道的JavaScript>,这书分为上中卷,内容非常丰富,认真细读,能学到非常多JavaScript的知识点,希望广大的前端同胞们,也入手看看这 ...
- 《你不知道的 JavaScript 上卷》 学习笔记
第一部分: 作用域和闭包 一.作用域 1. 作用域:存储变量并且查找变量的规则 2. 源代码在执行之前(编译)会经历三个步骤: 分词/此法分析:将代码字符串分解成有意义的代码块(词法单元) 解析/语法 ...
- JavaScript作用域闭包(你不知道的JavaScript)
JavaScript闭包.是JS开发project师必须深入了解的知识. 3月份自己曾撰写博客<JavaScript闭包>.博客中仅仅是简单阐述了闭包的工作过程和列举了几个演示样例,并没有 ...
随机推荐
- js跨域--服务器端设置
首先低版本浏览器是不支持的,我从网上搜的是[IE8.Firefox 3.5 及其以后的版本.Chrome浏览器.Safari 4 等已经实现了] 下面主要是针对服务器端设置Access-Control ...
- FIR系统的递归与非递归实现
首先,因为FIR的脉冲响应是有限长,所以总是可以非递归实现的: 其次,也可以用递归系统来实现它. 以滑动平均做例子,最直观的想法就是,每次来一个新的值,丢掉最老的,加上最新的: y[n]=y[n-1] ...
- Page.User.Identity.Name获取不到结果
如果在IIS部署后Page.User.Identity.Name获取不到值,需要检查以下设置: 1.web.config设置<authentication mode="Windows& ...
- Python处理Excel文档(xlrd, xlwt, xlutils)
简介 xlrd,xlwt和xlutils是用Python处理Excel文档(*.xls)的高效率工具.其中,xlrd只能读取xls,xlwt只能新建xls(不可以修改),xlutils能将xlrd.B ...
- TortoiseSVN 同步分支
对比工具可以使用 winmerge 和 beyond compare ,winmerge免费小巧,beyond compare功能更强大.这两款工具都比TortoiseSVN自带的对比工具要好一些. ...
- 328. Odd Even Linked List
Given a singly linked list, group all odd nodes together followed by the even nodes. Please note her ...
- (C# ) 解析XML。
解析XML有很多方法,之前用专门写的XMLProcess 或XMLHelper 解析类.其实有个较简单的解析就是用Linq查询. 例如有如下XML <?xml version="1.0 ...
- 想当然是编程最大的坑,记更新删除过期cookie无效有感
一般来说只要设置了cookie的过期时间,就可以实现删除cookie的作用. 可是我尝试了设置过期时间,清除cookie内容都无效. 最后才发现,我根本没有执行到那段设置过期的代码. 刚开始是因为登出 ...
- Java面试必备知识2
1 .三个Statment区别,用法 Statement,基本的:PreparedStatement是可编译的,提高效率,callablestatement,存储过程 2 .Cookie 答:临时co ...
- PLSQL_基础系列02_分组函数GROUP BY / ROLLUP / CUBE(案例)
2014-11-30 Created By BaoXinjian