网易JS面试题与Javascript词法作用域说明
调用对象位于作用域链的前端,局部变量(在函数内部用var声明的变量)、函数参数及Arguments对象都在函数内的作用域中——这意味着它们隐藏了作用域链更上层的任何同名的属性。
2010年9月14日,我去参加网易网页工程师招聘会,应聘JS工程师职位。有幸参加笔试,然后有幸栽在笔试,呵呵。废话少说,抓出音响极深的一题重新研究研究。
题目大概是:写出如下代码的输出结果并进行分析
var tt = 'aa';
function test(){
alert(tt);
var tt = 'dd';
alert(tt);
}
test();
“太简单了!”这是我当时看到这个题目是的第一想法,于是轻率答题竟成我的致命之伤。我的答案是——aa和dd,解析:第一次输出全局变量的结果,然后局部变量tt覆盖全局变量所引用的值,所以第二次输出结果是dd。
任何人见我如此作答,都会认为我是在扫盲——想法及其幼稚(我也这么认为)!
网易啊,怎么可能会满意于这种答案!
正确的答案应该是:undefined和dd
为什么第一次alert的结果是undefined呢?要解释得清楚明白需要用到Javascript的词法作用域。
Javascript中的函数“在定义它们的作用域里运行,而不是在执行它们的作用域里运行”,这是权威指南里抽象而精辟的总结。
Javascript的逻辑默认在一个全局作用域中执行,如以上程序段中的“var tt='aa';”就是定义一个全局作用域的全局变量(如果以上代码段不是摘自某个函数链的话)。而test()函数内部的逻辑必须在原有的作用域(全局 作用域)链再添加test函数本身的作用域(局部性)——这些思想几乎在每一种语言中都是如此定义的,然而Javascript作用域链的特别之处在于函 数内部能够嵌套函数的定义(这是闭包的基础。注:在JS中函数是唯一形式的代码作用域)
嵌套的内部函数可以调用外部函数(被嵌套的函数)的变量和其他嵌套函数(函数是一种数据)。如果是在外部函数内调用嵌套函数,那么调用对象不变,当 外部函数执行完毕后所有数据(包括外部函数和嵌套的内部函数)都将被垃圾回收机制收集——这一点还不能体现出‘闭包'的精华。有一种情况,就是 Javascript允许外部调用嵌套的内部函数,即使被嵌套函数已经被‘垃圾收集'——最常见的就是在‘某个函数'中用其嵌套的内部函数定义某些元素的 响应事件,页面载入的时候被嵌套函数(‘某个函数')已经执行完毕(被垃圾回收),但当事件触发的时候仍然会有响应的动作,而且响应函数中还可能调用到在 被嵌套函数(‘某个函数')中定义的变量最终值(不是被垃圾回收了吗?)。
关于闭包的知识和示例有很多资料可供查询,我不想叙述。
本文的重点是以下非常重要的细节:
调用对象位于作用域链的前端,局部变量(在函数内部用var声明的变量)、函数参数及Arguments对象都在函数内的作用域中——这意味着它们隐藏了作用域链更上层的任何同名的属性。
即,在以上程序片段中,test函数内部的“var tt='dd'”将会致使“var tt='aa'”在test函数被调用时完全被隐藏。而且,tt是在第一个alert语句之后定义,所以在调用到第一个alert时,tt是还没有被赋值 的。这样说可能会清楚一点,即,在定义test函数时,当定义第一个alert(tt)时,这里会记录tt是作用域链中的一个变量但不会记录它(tt)的 值,函数定义完毕后tt就添加到作用域里,所以第一个alert语句能够找到该作用域里的tt(即,相当于找到一个已经在函数内部声明,但未被赋值的 tt)。
以上程序片段的执行结果与以下片段的结果相同:
var tt = 'aa';
function test(){
var tt;
alert(tt);
tt = 'dd';
alert(tt);
}
test();
Javascript的作用域不可简单的用C++等语言的思维来理解啊!C++在调用函数之前必须先声明或定义,而Javascript没必要。在 Javascript中可以先调用函数,后再定义(不用在调用之前作任何声明)。因为在调用函数时,Javascript是向作用域链要函数的定义(函数在定义它们的作用域里运行,而不是在执行它们的作用域里运行)
如以上代码写成:
var tt = 'aa';
test(); //先调用后再定义
function test(){
alert(tt); //undefined
var tt = 'dd';
alert(tt); //dd
}
以上代码片段虽然能够得到相同的结果,但最好不要那样写啦,习惯不好,代码不好维护。
网易JS面试题与Javascript词法作用域说明的更多相关文章
- JavaScript词法作用域—你不知道的JavaScript上卷读书笔记(一)
前段时间在每天往返的地铁上抽空将 <你不知道的JavaScript(上卷)>读了一遍,这本书很多部分写的很是精妙,对于接触前端时间不太久的人来说,就好像是叩开了JavaScript的另一扇 ...
- JavaScript词法作用域与调用对象
关于 Javascript 的函数作用域.调用对象和闭包之间的关系很微妙,关于它们的文章已经有很多,但不知道为什么很多新手都难以理解.我就尝试用比较通俗的语言来表达我自己的理解吧. 作用域 Scope ...
- JavaScript 词法作用域不完全指北
在 JavaScript 作用域不完全指北 中,我们介绍了作用域的概念以及 JavaScript 引擎.编译器和作用域的关系.作用域有两种主要的工作模型:词法作用域和动态作用域.其中最为普遍的也是大多 ...
- 一道js面试题看变量的作用域
[问题]分别求下面程序的输出结果: 1. <script type="text/javascript"> var a = 10; sayHi(); function s ...
- JavaScript词法作用域经典练习题
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...
- 区分词法作用域(js)与动态作用域(精!)
在js学习中,词法作用域是必须要掌握的! 在这里,我将总结一下<你不知道的JS>一书中词法作用域的重点并分享给大家! 首先带来一段代码示例: function foo(){ console ...
- JS面试题及答案
一.JS闭包. f = function() {return true;}; g = function() {return false;}; (function() { if ...
- javascript一个作用域案例分析
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- JavaScript的作用域与作用域链
作用域 作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期.可以说,变量和函数在什么时候可以用,什么时候被摧毁,这都与作用域有关. JavaScript中,变量的作用域有全局 ...
随机推荐
- 科通芯城:用B2C的方式做B2B
上线两年,科通芯城的年收入有望突破50亿,一个传统分销商用2c的方式做b2b,也能进行自我革命. 文 | 王海天 这个网站的名字叫科通芯城,于2011年下半年在深圳正式上线,卖的商品是IC元器件,包括 ...
- 【HDOJ】5155 Harry And Magic Box
DP.dp[i][j]可以表示i行j列满足要求的组合个数,考虑dp[i-1][k]满足条件,那么第i行的那k列可以为任意排列(2^k),其余的j-k列必须全为1,因此dp[i][j] += dp[i- ...
- UVA253 Cube painting(数学)
题目链接. 分析: 用的<训练指南>上的方法.详见P17. 从6个面中选一个做顶面,再从剩下的4个面中选1个做正面,则此正方体唯一确定. 需要枚举共6*4=24种. #include &l ...
- 什么是Web Service?
Web service到底是什么:在什么情况下你应该使用Web service. 分布式应用程序和浏览器 研究一下当前的应用程序开发,你会发现一个绝对的倾向:人们开始偏爱基于浏览器的瘦客户应用程序.这 ...
- Java WeakHashMap 源码解析
前面把基于特定数据结构的Map介绍完了,它们分别利用了相应数据结构的特点来实现特殊的目的,像HashMap利用哈希表的快速插入.查找实现O(1)的增删改查,TreeMap则利用了红黑树来保证key的有 ...
- Hadoop2以来的历次升级(不含2.2.0及以下)
2015年7月06:release 2.7.1(稳定)请参阅 Hadoop 2.7.1发布说明 对131个bug修复和列表 从先前版本2.7.0补丁. 请看看 2.7.0章节列表的增强功能启用 第一个 ...
- java集合简介
java集合主要包括以下几点 Java 集合概述 Collection 接口 Iterator 接口 Set List Map Collections 工具类 Enumeration 1.java集合 ...
- vbs自学备份
最小化所有窗口: Set obj = CreateObject("Shell.Application")obj.MinimizeAll 最小化某窗口: Const strTitle ...
- wcf长连接
项目有用到wcf 大体是jquery + webservice + wcf(网页是客户端,wcf是服务端),现在需要服务端往客户端推送信息,本来是用客户端ajax访问 2秒一次访问服务端,后来觉得这 ...
- [Angular 2] Rendering an Observable Date with the Async and Date Pipes
Instead of simply pushing numbers on a timer into the template, now we'll move on to pushing actual ...