一道小题引发的深思

今天无意中看到一个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. xlat指令...

    ;就是一个串str1, lea ebx, str1 然后我们ebx+1总是加上的是一个字节, 无论(串是word, byte, dword) . .model flat .stack include ...

  2. Spark入门实战系列--9.Spark图计算GraphX介绍及实例

    [注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 .GraphX介绍 1.1 GraphX应用背景 Spark GraphX是一个分布式图处理 ...

  3. Network - SSH

    SSH(Secure Shell) https://wiki.wireshark.org/SSH   SSH 协议与OpenSSH详解 http://my.oschina.net/liting/blo ...

  4. Crumpet – 使用很简单的响应式前端开发框架

    Crumpet 是一个简单的响应式的基于 SASS/SCSS 的响应式前端框架,保持你的 HTML 代码简洁.内置尽量使用占位符选择器,以减少你的 HTML 标记的大小,没有凌乱的 HTML 代码.快 ...

  5. 1.Visual FoxPro 基础

    1.菜单栏的使用 ******************************* 方法一:鼠标点击 方法二:快捷键  Alt+F打开文件菜单 Alt+E打开编辑菜单 Alt+V打开显示菜单 Alt+P ...

  6. 【原创】Django-ORM基础

    概述 1.什么是ORM? ORM,即Object-Relational Mapping(对象关系映射),它的作用是在关系型数据库和业务实体对象之间作一个映射,这样,我们在具体的操作业务对象的时候,就不 ...

  7. HTML5 Web 客户端五种离线存储方式汇总

    最近折腾HTML5游戏需要离线存储功能,便把目前可用的几种HTML5存储方式研究了下,基于HT for Web写了个综合的实例,分别利用了Cookie.WebStorage.IndexedDB以及Fi ...

  8. EF总结

    1.Entity Framework 查询历史最严重bug求解十万火急 2.http://www.cnblogs.com/badly1984/p/3203565.html 3.Entity Frame ...

  9. 【Swift学习】Swift编程之旅---集合类型之Sets(七)

    Sets是存储无序的相同类型的值,你可以在顺序不重要的情况下使用Sets来替代数组,或者当你需要同一个值在集合中只出现一次时. 一.Sets类型语法  写作Set<Element>,Ele ...

  10. 《Inside UE4》-0-开篇

    <Inside UE4>-0-开篇 InsideUE4   前言 VR行业发展是越来越火热了,硬件设备上有HTC VIVE,Oculus rift,PS VR,各种魔镜:平台上有Steam ...