网易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 相关文章推荐
下载网站打开页面后间隔多少时间才显示下载链接地址的代码
Apr 25 Javascript
基于jQuery的Tab选项框效果代码(插件)
Mar 01 Javascript
cookie中的path与domain属性详解
Dec 18 Javascript
多种方法实现360浏览器下禁止自动填写用户名密码
Jun 16 Javascript
jquery中的常用事件bind、hover、toggle等示例介绍
Jul 21 Javascript
JavaScript对象数组如何按指定属性和排序方向进行排序
Jun 15 Javascript
JavaScript数据结构学习之数组、栈与队列
May 02 Javascript
vue.js实现备忘录功能的方法
Jul 10 Javascript
详解webpack2+node+react+babel实现热加载(hmr)
Aug 24 Javascript
实例讲解v-if和v-show的区别
Jan 31 Javascript
JS求1到任意数之间的所有质数的方法详解
May 20 Javascript
微信小程序webSocket的使用方法
Feb 20 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
ie6 动态缩略图不显示的原因
2009/06/21 PHP
JQuery将文本转化成JSON对象需要注意的问题
2011/05/09 Javascript
推荐10个超棒的jQuery工具提示插件
2011/10/11 Javascript
jQuery 瀑布流 绝对定位布局(二)(延迟AJAX加载图片)
2012/05/23 Javascript
ComboBox 和 DateField 在IE下消失的解决方法
2013/08/30 Javascript
js从10种颜色中随机取色实现每次取出不同的颜色
2013/10/23 Javascript
创建你的第一个AngularJS应用的方法
2015/06/16 Javascript
jQuery+ajax实现文章点赞功能的方法
2015/12/31 Javascript
js流动式效果显示当前系统时间
2016/05/16 Javascript
jquery自动补齐功能插件flexselect用法示例
2016/08/06 Javascript
使用jQuery的toggle()方法对HTML标签进行显示、隐藏的方法(示例)
2016/09/01 Javascript
原生JS轮播图插件
2017/02/09 Javascript
基于vue2.0+vuex的日期选择组件功能实现
2017/03/13 Javascript
ExtJs的Ext.Ajax.request实现waitMsg等待提示效果
2017/06/14 Javascript
VueJs单页应用实现微信网页授权及微信分享功能示例
2017/07/26 Javascript
基于vue-ssr的静态网站生成器VuePress 初体验
2018/04/17 Javascript
angularJs中json数据转换与本地存储的实例
2018/10/08 Javascript
Vue.js结合bootstrap前端实现分页和排序效果
2018/12/29 Javascript
jQuery实现的别踩白块小游戏完整示例
2019/01/07 jQuery
详解如何搭建mpvue框架搭配vant组件库的小程序项目
2019/05/16 Javascript
分析python服务器拒绝服务攻击代码
2014/01/16 Python
Python cookbook(数据结构与算法)同时对数据做转换和换算处理操作示例
2018/03/23 Python
Python3 chardet模块查看编码格式的例子
2019/08/14 Python
Python 忽略文件名编码的方法
2020/08/01 Python
详解python内置模块urllib
2020/09/09 Python
Spartoo英国:欧洲最大的网上鞋店
2016/09/13 全球购物
澳大利亚票务和娱乐市场领导者:Ticketmaster
2017/03/03 全球购物
台湾流行服饰购物平台:OB严选
2018/01/21 全球购物
台湾最大银发乐活百货:乐龄网
2018/05/21 全球购物
澳大利亚百货商店中销量第一的商务衬衫品牌:Van Heusen
2018/07/26 全球购物
班训口号大全
2014/06/18 职场文书
乡党委干部党的群众路线教育实践活动个人对照检查材料思想汇报
2014/10/01 职场文书
2015年人民调解工作总结
2015/05/18 职场文书
复活读书笔记
2015/06/29 职场文书
pytorch常用数据类型所占字节数对照表一览
2021/05/17 Python
基于PyQt5制作一个群发邮件工具
2022/04/08 Python