一道变态的Javascript面试题
转载http://cymoft.blog.51cto.com/324099/1260099
|
1
2
3
4
5
6
7
8
9
|
f = function() {return true;}; g = function() {return false;}; (function() { if (g() && [] == ![]) { f = function f() {return false;}; function g() {return true;} } })(); alert(f()); // true or false ? |
此题的关键是第4行的if条件
g() && [] == ![]
这里有三个关键的点,
第一,g()在这里执行的到底是第2行的函数还是第6行的函数?
第二,Javascript里面的falsy值
第三,== 运算符的运算逻辑
先看第一点,我不喜欢卖关子,直接揭晓答案,第4行的g(),执行的是第6行的函数,返回值的是true。
这里的考点是javascript的Execution Context, Variable Object, Scope Chain等概念,简单来说,Javascript的作用域是函数级别的,并且在函数刚开始执行时,就会对函数体内所有的变量及内部函数进行声明,不会等到写的那一行,也就是说,即使你一个内部函数写在包含它的函数的最后面,你在第一行也照样用。回到这道题,我们本来有一个全局的函数g,写在第二行,但是进入第4行,我们进入了一个匿名函数的内部,这个匿名函数里面又在第6行声明一个局部函数g,于是这个局部函数覆盖了全局函数,因此,第4行调用的是写在第6行的局部函数g。
既然g()返回的true,那么接下来就要看 [] == ![] 这句极诡异的比较式的值,这里是拿一个空数组去跟空数组的取反的值比较,初看起来肯定是false啊。可惜,它的值是true,请不要崩溃,让我来仔细分析javascript的操蛋的逻辑。
首先我们看右边的 ![],对一个空数组取反,那么意味着先要把空数组转化为一个boolean值,再取反,在javascript中,所有对象在作为boolean值使用时,都是表示true,空数组也是一个对象,所以空数组也是true,那么对空数组取反,等价于 !true,所以,![]的值为false。
好了,既然右边说完了是false,现在我们就等于在看 [] == false,刚才不是说了空数组是对象是true么,那很明显这个比较就是true == false, 就是返回false对不对?可惜不是,这个比较会返回true,看到这你抓狂了没有,想不通了有没有?先冷静,我来告诉你发生了什么,根据 ECMAScript的对于==的规范,这样一个表达式最终是这么做的
1.把右边的false转成数值0
2.把左边的对象转成字符串,空数组转成字符串就是空字符串
3.把空字符串转成数值,结果是0
4.比较0 == 0,返回true
这里的关键是第2步,数组会先转成空字符串,空字符其实本身就是一个falsy值。
好了,到底谜底全部解开,第4行的if中的判断为实际上是true && true,结果还是true,于是全局函数f在第5行被重新赋值,所以在第9行执行的是第5行被重新赋值的f,返回false。
关于第5行其实还有点小问题,为什么这里的function f() {return false;}没有像第6行的函数g一样被当做一个局部函数,如果这样的话,那么f也是一个局部函数,对f的赋值应该不会影响全局函数f。这里的原因在于,整个第5行不是一个函数声明,第5行作为一个整体其实是一条赋值语句,所以这里的f不会被当做局部变量。
一道变态的Javascript面试题的更多相关文章
- 一道简单的JavaScript面试题
好久没更新博客了,随便写点东西吧. 自从工作之后就特别忙,忙的过程中有时候挺迷茫的,可能是大多数时候写的都是简单的业务代码,很久没好好充电了.最近一直在零碎的上班路上等电梯时间里面学习<图解HT ...
- 一道 JavaScript 面试题
有一道 JavaScript 面试题. f = function () { return true; }; g = function () { return false; }; (function() ...
- 学生问的一道javascript面试题[来自腾讯]
function Parent() { this.a = 1; this.b = [1, 2, this.a]; this.c = { demo: 5 }; this.show = function ...
- 你应该知道的25道Javascript面试题
题目来自 25 Essential JavaScript Interview Questions.闲来无事,正好切一下. 一 What is a potential pitfall with usin ...
- 一道变态的js题
一道腾讯js面试题 题目如下: f = function() {return true;}; g = function() {return false;}; (function() { if (g() ...
- 174道 JavaScript 面试题,助你查漏补缺
最近在整理 JavaScript 的时候发现遇到了很多面试中常见的面试题,本部分主要是作者在 Github 等各大论坛收录的 JavaScript 相关知识和一些相关面试题时所做的笔记,分享这份总结给 ...
- 互联网中级Javascript面试题
互联网中级Javascript面试题 1.实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number.String.Object.Array.Boolean)进行值复制 ...
- 互联网公司前端初级Javascript面试题
互联网公司前端初级Javascript面试题 1.JavaScript是一门什么样的语言,它有哪些特点?(简述javascript语言的特点)JavaScript是一种基于对象(Object)和事件驱 ...
- 人人网javascript面试题
JavaScript面试题要求:以下题目必须从一至四题中,选出三道题,使用原生代码实现,不可使用任何框架,第五题为选作题. 一. 在页面的固定区域内实现图片的展示 <ignore_ ...
随机推荐
- 敏捷开发(2)-Scrum
什么是SCRUM Scrum的英文意思是橄榄球运动的一个专业术语,表示“争球”的动作:把一个开发流程的名字取名为Scrum,我想你一定能想象出你的开发团队在开发一个项目时,大家像打橄榄球一样迅速.富有 ...
- 使用acs-engine在Azure中国区部署kubernetes集群详解
转载请注明出处:http://www.cnblogs.com/wayneiscoming/p/7649642.html 1. acs-engine简介 ACS是微软在2015年12月推出的一项基于容器 ...
- js的事件循环绑定和jQuery的隐式迭代
js的事件循环绑定和jQuery的隐式迭代 js事件循环绑定 jQuery隐式迭代 先举一个例子:给定一个ul,点击列表内的每一个li元素,使它的背景色变红,下边分别用js代码和jQuery实现. & ...
- C#中的协变(Covariance)和逆变(Contravariance)
摘要 ● 协变和逆变的定义是什么?给我们带来了什么便利?如何应用? ● 对于可变的泛型接口,为什么要区分成协变的和逆变的两种?只要一种不是更方便吗? ● 为什么还有不可变的泛型接口,为什么有的泛型接口 ...
- ASP 文件内部访问数据库的通常途径
创建至数据库的 ADO 连接(ADO connection) 打开数据库连接 创建 ADO 记录集(ADO recordset) 打开记录集(recordset) 从数据集中提取你所需要的数据 关闭数 ...
- LeetCode 229. Majority Element II (众数之二)
Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorit ...
- 四、MVC简介
一.高内聚.低耦合 大学的时候,上过一门叫<软件工程>的课程,课程中讲到了耦合,解耦等相关的词汇,当时很懵懂,不解其意. 耦合:是指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影 ...
- 【Salvation】——关卡功能&数据库基础实现
写在前面:项目的关卡功能和数据库基础实现是小组其他成员实现的部分,这里作为学习总结.关卡功能块使用C#语言编写脚本,在Unity3D游戏引擎的环境中实现,数据库功能块使用PHP作为服务端获取MySQL ...
- Ionic3 组件懒加载
使用懒加载能够减少程序启动时间,减少打包后的体积,而且可以很方便的使用路由的功能. 使用懒加载: 右侧红色区域可以省略掉(引用.声明也删掉) 若使用ionic命令新建page,则无需进行下面的操作,否 ...
- Ignatius and the Princess II
Ignatius and the Princess II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Jav ...