一道小题引发的深思

今天无意中看到一个js笔试题,不由得想起初学js那会被各种题目狂虐的心酸,虽说现在也会被笔试题所虐,但毕竟比之前好了很多,下面就是我的个人理解,欢迎拍砖、指正:

var x = 1;
function printx(){
console.log(x); } function show(f){
var x = 2;
(function(){
f();
})()
} show(printx); //1

结果后台会打印1,而不是2。这有些不合常理,因为很多人会错误的认为:函数show中的f()在执行时,由于本作用域中没有x,所以会向上层作用域寻找x,当找到上层函数show的作用域中时发现 var x=2,这时就把x确定为2,否则会继续向上找,直至window。。。终于用到所谓的“作用域链”啦!大喜,其实这样想你就错了!

第一:首先有这么一个名词叫“自由变量”,自由变量是指:如果作用域(函数)A中使用到了变量x,而x并不是在作用域(函数)A中定义,那么对于作用域(函数)A来说,x就是A的自由变量。

第二:理解这么一句话:js没有块级作用域,仅有的块级作用域是用函数来实现的,也就是说只有函数能创建出一块独立的作用域。if、for代码块都不行!所以本文中一个作用域可以理解为一个函数。

第三:函数的作用域在函数定义时就已经确定,而不是在执行时确定。

对于嵌套函数来说按照上述:寻找自由变量是沿作用域链向上一层层查找,这样理解是对的。但是这样理解太片面,甚至会产生错误,就比如上面这道题。正确的理解应该是:寻找自由变量时会到创建这个函数(作用域)的那个作用域中寻找。而创建这个函数的作用域并不一定是它位置上的父级作用域,(并不是在代码结构上包含,就是子父关系)上面这道题就是这种情况:函数show中把printx函数作为参数传入执行,在执行时会寻找创建它的那个作用域,很明显创建printx函数的作用域并不是show,而是全局window(因为printx函数在window中创建),所以它会寻找全局window中的x,此x为1。 所以会打印1,这才是正解。

不知道我解释的清不清楚,总之:函数使用自由变量时,会到创建这个函数的那个作用域中寻找。“向父级作用域中寻找”可能会存在偏差。(不足之处欢迎指正!)

再补充两道,加深理解

本文的评论里还有两道更加通俗易懂的两道题,征得热心博友theWalker的同意,把他给出的两个demo也展示给大家,希望对你有所帮助:

function a(){
console.log(b)
}
function c(){
var b = 1;
a()
}
c() //b is not defined /****************************************/ var b = 2;
function a(){
console.log(b)
}
function c(){
var b = 1;
a()
}
c() //

常让人误解的一道js小题的更多相关文章

  1. 一些js小题(一)

    一些js小题,掌握这些对于一些常见的面试.笔试题应该很有帮助: var a=10; function aa(){ alert(a); } function bb(){ aa(); } bb();//1 ...

  2. 一道常被人轻视的前端JS面试题

    前言 年前刚刚离职了,分享下我曾经出过的一道面试题,此题是我出的一套前端面试题中的最后一题,用来考核面试者的JavaScript的综合能力,很可惜到目前为止的将近两年中,几乎没有人能够完全答对,并非多 ...

  3. 一道常被人轻视的前端JS面试题(转)

    分享下我曾经出过的一道面试题,此题是我出的一套前端面试题中的最后一题,用来考核面试者的JavaScript的综合能力,很可惜到目前为止的将近两年中,几乎没有人能够完全答对,并非多难只是因为大多面试者过 ...

  4. js排序--一道js数据结构题

    给一个数组: [{ GroupMark: "", GroupName: "hao", SendTime: '123', SendContent: "1 ...

  5. 第24篇 js小知识和“坑”

    前面说了说了js的相关知识,基本上除了语法外,把项目常用的知识做了一个梳理,现在说下js的其它方面的知识,这些知识不成体系,属于不理解对于一般开发没什么太多影响,但如果理解清楚,可以更好去开发. js ...

  6. React.js 小书介绍

    React.js 小书 Github 关于作者 这是一本关于 React.js 的小书. 因为工作中一直在使用 React.js,也一直以来想总结一下自己关于 React.js 的一些知识.经验.于是 ...

  7. 一个js小游戏----总结

    花了大概一天左右的功夫实现了一个js小游戏的基本功能,类似于“雷电”那样的小游戏,实现了随即怪物发生器,碰撞检测,运动等等都实现了,下一个功能是子弹轨迹,还有其他一些扩展功能,没有用库,也没有用web ...

  8. React.js 小书 Lesson25 - 实战分析:评论功能(四)

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson25 转载请注明出处,保留原文链接和作者信息. (本文未审核) 目前为止,第二阶段知识已经基本 ...

  9. React.js 小书 Lesson24 - PropTypes 和组件参数验证

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson24 转载请注明出处,保留原文链接和作者信息. 我们来了到了一个非常尴尬的章节,很多初学的朋友 ...

随机推荐

  1. java中finally和return的执行顺序

    注意:return的位置... 从这几个例子中可以看到,如果try之前没有有条件的return,则try..catch..finally语句块中的语句都是顺序执行(如果try中或者catch中 有re ...

  2. JavaScript作用域原理(三)——作用域根据函数划分

    一.一个for实例 <p id="scope3" style="color:red"></p> var pscope3 = docume ...

  3. LeetCode:Move Zeroes

    LeetCode:Move Zeroes [问题再现] Given an array nums, write a function to move all 0's to the end of it w ...

  4. Linux - 变量

    printenv - print all or part of environment 显示所有变量:print 显示某个变量:print <variable name> 或者 echo ...

  5. Android Fragment完全解析

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8881711 我们都知道,Android上的界面展示都是通过Activity实现的, ...

  6. Linux安装配置tomcat

    1.首先配置好jdk 查看java版本:java -verson 1.官网下载jdk 2.tar -zxvf xxxx.tar.gz   解压 3.配置环境变量 <1># vi /etc/ ...

  7. 关于Entity Framework中的Attached报错相关解决方案的总结

    关于Entity Framework中的Attached报错的问题,我这里分为以下几种类型,每种类型我都给出相应的解决方案,希望能给大家带来一些的帮助,当然作为读者的您如果觉得有不同的意见或更好的方法 ...

  8. linux的计划

    我接触linux也有好几年了,至少有5年了.最近公司在搞内部培训,人人都可以报名培训别人.想到自己在linux浸淫多年,应该出来出一份力.一直以来想就linux写一个专题.今天刚好在做相关的ppt,借 ...

  9. 30天C#基础巩固-----多态,工厂模式

         自己要有自信,相信自己可以找到好的工作.面对校招,企业更加看重自己的基础,这30天就把C#的基础好好的复习,学习下.笔记一定要认真的记录,这样自己复习回顾的时候就有了可以参考的东西了. 一: ...

  10. Git版本控制工具学习

    Git代码管理工具学习 分布式管理工具:git 相比较svn它更加的方便,基本上我们的操作都是在本地进行的. Git文件的三种状态:已提交,已修改,以暂存. 已提交:表示文件已经被保存到本地数据库. ...