网易JS面试题与Javascript词法作用域说明


Posted in Javascript onNovember 09, 2010

调用对象位于作用域链的前端,局部变量(在函数内部用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 
}

以上代码片段虽然能够得到相同的结果,但最好不要那样写啦,习惯不好,代码不好维护。
Javascript 相关文章推荐
jQuery 渐变下拉菜单
Dec 15 Javascript
jquery清空表单数据示例分享
Feb 13 Javascript
JS选项卡动态替换banner图片路径的方法
May 11 Javascript
jQuery循环遍历子节点并获取值的方法
Apr 14 Javascript
如何清除IE10+ input X 文本框的叉叉和密码输入框的眼睛图标
Dec 21 Javascript
基于JS设计12306登录页面
Dec 28 Javascript
浅谈Javascript事件对象
Feb 05 Javascript
纯原生js实现贪吃蛇游戏
Apr 16 Javascript
AngularJS 验证码60秒倒计时功能的实现
Jun 05 Javascript
vue-i18n结合Element-ui的配置方法
May 20 Javascript
对node通过fs模块判断文件是否是文件夹的实例讲解
Jun 10 Javascript
微信小程序 腾讯地图SDK 获取当前地址实现解析
Aug 12 Javascript
浅谈Javascript嵌套函数及闭包
Nov 09 #Javascript
JavaScript高级程序设计 扩展--关于动态原型
Nov 09 #Javascript
关于JavaScript定义类和对象的几种方式
Nov 09 #Javascript
JS图片浏览组件PhotoLook的公开属性方法介绍和进阶实例代码
Nov 09 #Javascript
一个javascript图片阅览组件
Nov 09 #Javascript
js中格式化日期时间型数据函数代码
Nov 08 #Javascript
window.location.hash 使用说明
Nov 08 #Javascript
You might like
简单了解将WordPress中的工具栏移到底部的小技巧
2015/12/31 PHP
php自动载入类用法实例分析
2016/06/24 PHP
基于PHP实现短信验证码接口(容联运通讯)
2016/09/06 PHP
PHP实现Unicode编码相互转换的方法示例
2020/11/17 PHP
php实现微信和支付宝支付的示例代码
2020/08/11 PHP
5个JavaScript经典面试题
2014/10/13 Javascript
node.js中的fs.statSync方法使用说明
2014/12/16 Javascript
jquery ui resize 中border-box的bug修正
2015/04/26 Javascript
jquery SweetAlert插件实现响应式提示框
2015/08/18 Javascript
jquery validate和jquery form 插件组合实现验证表单后AJAX提交
2015/08/26 Javascript
jquery根据一个值来选中select下的option实例代码
2016/08/29 Javascript
聊一聊JS中的prototype
2016/09/29 Javascript
js实现表单提交后不重新刷新当前页面
2016/11/30 Javascript
jQuery中页面返回顶部的方法总结
2016/12/30 Javascript
Ionic3 UI组件之autocomplete详解
2017/06/08 Javascript
使用原生js封装的ajax实例(兼容jsonp)
2017/10/12 Javascript
node.js的http.createServer过程深入解析
2019/06/06 Javascript
pageGroup.js实现分页功能
2019/07/27 Javascript
vue设置动态请求地址的例子
2019/11/01 Javascript
Quasar Input:type="number" 去掉上下小箭头 实现加减按钮样式功能
2020/04/09 Javascript
微信小程序实现简单的select下拉框
2020/11/23 Javascript
python简单实现基于SSL的IRC bot实例
2015/06/15 Python
python内置数据类型之列表操作
2018/11/12 Python
如何用Python破解wifi密码过程详解
2019/07/12 Python
tensorflow实现tensor中满足某一条件的数值取出组成新的tensor
2020/01/04 Python
HTML5去掉输入框type为number时的上下箭头的实现方法
2020/01/03 HTML / CSS
独特的礼品和创新的科技产品:The Grommet
2018/02/24 全球购物
普天C++笔试题
2016/03/20 面试题
医务工作者先进事迹材料
2014/01/26 职场文书
竞选劳动委员演讲稿
2014/04/28 职场文书
党员承诺书格式
2014/05/21 职场文书
2014年教师党员自我评价范文
2014/09/22 职场文书
2016党员党课心得体会
2016/01/07 职场文书
php 解析非标准json、非规范json
2021/04/01 PHP
pytorch 如何使用batch训练lstm网络
2021/05/28 Python
简单介绍Python的第三方库yaml
2021/06/18 Python