网易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 相关文章推荐
node.js实现博客小爬虫的实例代码
Oct 08 Javascript
微信小程序  网络请求API详解
Oct 25 Javascript
Bootstrop实现多级下拉菜单功能
Nov 24 Javascript
js实现移动端编辑添加地址【模仿京东】
Apr 28 Javascript
JS中利用FileReader实现上传图片前本地预览功能
Mar 02 Javascript
javaScript中"=="和"==="的区别详解
Mar 16 Javascript
在小程序Canvas中使用measureText的方法示例
Oct 19 Javascript
微信小程序实现跳转的几种方式总结(推荐)
Apr 24 Javascript
js计算两个时间差 天 时 分 秒 毫秒的代码
May 21 Javascript
js将日期格式转换为YYYY-MM-DD HH:MM:SS
Sep 18 Javascript
vue 获取到数据但却渲染不到页面上的解决方法
Nov 19 Vue.js
详解vite2.0配置学习(typescript版本)
Feb 25 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
WindowsXP中快速配置Apache+PHP5+Mysql
2008/06/05 PHP
PHP 命令行工具 shell_exec, exec, passthru, system详细使用介绍
2011/09/11 PHP
shopex主机报错误请求解决方案(No such file or directory)
2011/12/27 PHP
修复ShopNC使用QQ 互联时提示100010 错误
2015/11/08 PHP
浅析PHP7新功能及语法变化总结
2016/06/17 PHP
php设计模式之工厂方法模式分析【星际争霸游戏案例】
2020/01/23 PHP
firefox和IE系列的相关区别整理 以备后用
2009/12/28 Javascript
『JavaScript』限制Input只能输入数字实现思路及代码
2013/04/22 Javascript
对JavaScript中this指针的新理解分享
2015/01/31 Javascript
JS使用post提交的两种方式
2015/12/03 Javascript
JavaScript数据绑定实现一个简单的 MVVM 库
2016/04/08 Javascript
JS组件Bootstrap Table布局详解
2016/05/27 Javascript
jquery mobile 实现自定义confirm确认框效果的简单实例
2016/06/17 Javascript
浅谈angular4生命周期钩子
2017/09/05 Javascript
使用命令行工具npm新创建一个vue项目的方法
2017/12/27 Javascript
swiper移动端轮播插件(触碰图片之后停止轮播)
2017/12/28 Javascript
详解webpack编译速度提升之DllPlugin
2019/02/05 Javascript
vue请求数据的三种方式
2020/03/04 Javascript
[02:58]献给西雅图的情书_高清
2014/05/29 DOTA
浅谈Python的异常处理
2016/06/19 Python
深入浅析python3中的unicode和bytes问题
2019/07/03 Python
Python叠加两幅栅格图像的实现方法
2019/07/05 Python
python飞机大战pygame游戏框架搭建操作详解
2019/12/17 Python
爬虫代理池Python3WebSpider源代码测试过程解析
2019/12/20 Python
python如何查看网页代码
2020/06/07 Python
8种常用的Python工具
2020/08/05 Python
TensorFlow2.0使用keras训练模型的实现
2021/02/20 Python
css3与html5实现响应式导航菜单(导航栏)效果分享
2014/02/12 HTML / CSS
使用HTML5的链接预取功能(link prefetching)给网站提速
2012/12/13 HTML / CSS
纽约复古灵感的现代珠宝品牌:Lulu Frost
2018/03/03 全球购物
Cynthia Rowley官网:全球领先的生活方式品牌
2020/10/27 全球购物
实现向右循环移位
2014/07/31 面试题
养殖项目策划书范文
2014/01/13 职场文书
《将心比心》教学反思
2014/04/08 职场文书
万能检讨书
2015/01/27 职场文书
婚宴领导致辞
2015/07/28 职场文书