有一道 JavaScript 面试题。

f = function () { return true; };
g = function () { return false; }; (function() {
if (g() && [] == ![]) {
f = function () { return false; };
function g() { return true; }
}
})();
console.info(f());

首先看前两行

var f = function () { return true; };
var g = function () { return false; };

这两行定义了两个变量,而不是函数定义,变量是可以重新赋值的。

第四行就比较有趣了

(function () {
if (g() && [] == ![]) {
f = function () { return false; };
function g() { return true; }
}
})();

在 if 条件中调用了函数 g(),但是,这个 g 是第二行定义的函数 g 吗?答案是否定的,因为在匿名函数中又定义了函数 g,局部的定义覆盖了外部的定义,所以,这里调用的是内部函数 g,返回为 true。第一个条件通过,进入第二个条件。

其实,最有趣的是第二个条件 [] == ![] 。

先看 ![] ,在 JavaScript 中,当用于布尔运算的时候,比如在这里,对象的非空引用被视为 true,空引用 null 则被视为 false。由于这里不是一个 null, 而是一个没有元素的数组,所以 [] 被视为 true, 而 ![] 的结果就是 false 了,如果你在 Visual Studio 的编辑器中输入,就会直接看到提示,表达式永远为假。

当一个布尔值参与到条件运算的时候,true 会被看作 1, 而 false 会被看作 0,见这里的说明: Javascript 中的相等与不等

现在条件变成了 [] == 0 的问题了,当一个对象参与条件比较的时候,它会被求值,求值的结果是数组成为一个字符串,[] 的结果就是 '' ,而 '' 会被当作 0 ,所以,条件成立。

条件内的代码如下:

f = function () { return false; };
function g() { return true; }

注意 f 的前面没有 var ,所以,不是局部变量,因此,这里会通过闭包访问到外部的变量 f, 重新赋值,现在执行 f 函数返回值已经成为 false 了。

至于 g 则不会有这个问题,这里是一个函数内定义的 g,不会影响到外部的 g 函数。

最后一行的结果自然也就出来了,就是 false。

---------------------------------------------------------------------------------------------------

今天又同学说到执行的结果不同,我原来是在 Chrome 测试的,现在重新检查一下发现是有问题的。

Chrome 在执行到签到函数的时候,是先发现 g 函数重新定义了,覆盖了外部的定义,满足条件执行,就是上面的说明。

在 FireFox 中,直到执行到 if 语句之前,是不会看内部的 g 函数定义的,所以条件根本就不会满足,在执行条件判断之后,才会处理内部的函数定义,但是由于条件没有满足,所以 f 不会被重新定义。返回结果就成为 true.

在 IE 中,最为特殊,在进入内部函数之后之后,g 既不是外部的定义,也不是内部的定义,而是神奇地成为 undefined 。直接会抛出异常。如果内部没有定义函数 g就可以访问到外部的 g 函数。

最新文章

  1. iOS开发之多种Cell高度自适应实现方案的UI流畅度分析
  2. spring boot 调试 - 热部署
  3. Centos中jdk的环境配置
  4. COGS 577 蝗灾
  5. asp.net如何在前台利用jquery Ajax调用后台方法
  6. 2014 Super Training #8 B Consecutive Blocks --排序+贪心
  7. ylb:多表的连接与练习(第三方关联表的应用)
  8. Jquery中$与$.fn的差别
  9. NOPI读取EXCEL
  10. h.264并行解码算法3D-Wave实现(基于多核共享内存系统)
  11. 基于android的Socket通信
  12. (转载)php的类中可以不定义成员变量,直接在构造方法中使用并赋值吗?
  13. iTunes备份文件路径
  14. 三角形(hd1249)
  15. MySQL Replicationation进阶
  16. Hello,Kubernetes
  17. 17082 两个有序数序列中找第k小(优先做)
  18. MySQL之sql文件的导入导出
  19. HTML超链接之伪类注意事项
  20. Spring基础系列--AOP实践

热门文章

  1. 超强封装的RichTextBox控件(C#源码)
  2. openssl与cryptoAPI交互AES加密解密
  3. 基础:从概念理解Lucene的Index(索引)文档模型
  4. bzoj2618: [Cqoi2006]凸多边形
  5. 从IT匹配业务如何走向IT引领业务
  6. 151. Reverse Words in a String
  7. eclipse下编译hadoop源代码(转)
  8. solr基于jetty容器配置后台登陆角色用户名密码
  9. ADF_Starting系列5_使用ADF开发富Web应用程序之维护User Interface(Part2)
  10. DBA_Oracle Erp R12安装虚拟机镜像IP修正(案例)