关于函数声明表达式的一道题目
来源:互联网 发布:游戏美工就业前景 编辑:程序博客网 时间:2024/04/30 09:55
f = function() { return true; };
g = function() { return false; };
( function() {
if (g() && [] == ![]) {
f = function f() { return false; };
function g() { return true; };
}
})();
f(); // What's the result?
答案在最下边:
f = function() { return true; }; // 1
g = function() { return false; }; // 2
(function() { // F
// A
if (g() && [] == ![]) {
f = function f() { return false; }; // 3
function g() { return true; }; // 4
}
})();
f(); // What's the result?
IE 6,7,8 会让函数声明体 3(错误地) 和 4(正确地) 在 A 处生效,于是 F 中,f 和 g 都是局部的了。这样,外界的 f 根本没有被赋值,结果是 true。等价的代码是:
f = function() { return true; }; // 1
g = function() { return false; }; // 2
(function() { // F
var f, g; // A
f = function(){ return false };
g = function(){ return true };
if (g() && [] == ![]) {
f = function () { return false; }; // 3
// function g() { return true; }; // 4
}
})();
f(); // What's the result?
Firefox 则是因为支持条件函数定义(1),在 A 处 3 和 4 都没有生效,导致 if 分支不成立,同样没有给外界 f 赋值,得到 true。精确描述它的行为很难,下面是一个等效的代码:
f = function() { return true; }; // 1
g = function() { return false; }; // 2
(function() { // F
var g1; // A
g1 = g;
if (g() && [] == ![]) {
g1 = function () { return true; };
f = function () { return false; }; // 3
// function g() { return true; }; // 4
}
})();
f(); // What's the result?
Chrome、Safari、IE9 beta 则依照了 ECMA 之规范,只有声明 4 在 A 处生效,等效代码是:
f = function() { return true; }; // 1
g = function() { return false; }; // 2
(function() { // F
var g = function () { return true; }; // A
if (g() && [] == ![]) {
f = function () { return false; }; // 3
// function g() { return true; }; // 4
}
})();
f(); // What's the result?
结果得到 false。
lifesinger说我分析的不深入,好,我将代码加了钩子后捕获各种浏览器的输出,加钩子的代码是:
var trace = function(m, x){console.log(m + ': ' + x); return x};
f = function() { return true; }; // 1
g = function() { return false; }; // 2
trace('[1f] now f', f);
trace('[1g] now g', g);
(function() { // F
trace('[2f] now f', f);
trace('[2g] now g', g);
if (trace('g() && [] == ![]', trace('g()',g()) && trace('[] == ![]', [] == trace('![]', ![])))) {
trace('[3f] now f', f);
trace('[3g] now g', g);
f = function f() { return 0; }; // 3
function g() { return 1; } // 4
trace('[4f] now f', f);
trace('[4g] now g', g);
}
trace('[5f] now f', f);
trace('[5g] now g', g);
})();
trace('[6f] now f', f);
trace('[6g] now g', g);
f()
chorme 6、Safari 5 的输出结果是:
[1f] now f: function () { return true; }
[1g] now g: function () { return false; }
[2f] now f: function () { return true; }
[2g] now g: function g() { return 1; }
g(): true
![]: false
[] == ![]: true
g() && [] == ![]: true
[3f] now f: function () { return true; }
[3g] now g: function g() { return 1; }
[4f] now f: function f() { return 0; }
[4g] now g: function g() { return 1; }
[5f] now f: function f() { return 0; }
[5g] now g: function g() { return 1; }
[6f] now f: function f() { return 0; }
[6g] now g: function () { return false; }
false
可以注意 [2f] 和 [2g] 的输出,chrome 6 遵守了 ECMA 的规定,忽略 3 处的函数声明,启用了 4 处的声明。所以你可以看到 [2g] 的里面是一个 1。而 f 则是直到 [4f] 才赋值为 function f(){return 0}。
Firefox 3.6.8 的输出结果是:
[1f] now f: function () { return true; }
[1g] now g: function () { return false; }
[2f] now f: function () { return true; }
[2g] now g: function () { return false; }
g(): false
g() && [] == ![]: false
[5f] now f: function () { return true; }
[5g] now g: function () { return false; }
[6f] now f: function () { return true; }
[6g] now g: function () { return false; }
true
可以看出少了好几行,这是因为 if 的短路所致。因为我们把 function g() 给弄进了 if 里,所以 [2g] 处的结果仍然是外界的 g。
IE 6,7,8 的输出是:
日志: [1f] now f: function() { return true; }
日志: [1g] now g: function() { return false; }
日志: [2f] now f: function f() { return 0; }
日志: [2g] now g: function g() { return 1; }
日志: g(): true
日志: ![]: false
日志: [] == ![]: true
日志: g() && [] == ![]: true
日志: [3f] now f: function f() { return 0; }
日志: [3g] now g: function g() { return 1; }
日志: [4f] now f: function f() { return 0; }
日志: [4g] now g: function g() { return 1; }
日志: [5f] now f: function f() { return 0; }
日志: [5g] now g: function g() { return 1; }
日志: [6f] now f: function() { return true; }
日志: [6g] now g: function() { return false; }
true
IE 6,7,8 错误地启用了 3 处的声明,把 F 里定义了一个局部变量 f,所以 [2f] 处得到了不同的结果。因为 f 已经成为 F 的局部变量,因此外界的 f 没有收到影响。
IE9 的输出是:
日志: [1f] now f: function() { return true; }
日志: [1g] now g: function() { return false; }
日志: [2f] now f: function() { return true; }
日志: [2g] now g: function g() { return 1; }
日志: g(): true
日志: ![]: false
日志: [] == ![]: true
日志: g() && [] == ![]: true
日志: [3f] now f: function() { return true; }
日志: [3g] now g: function g() { return 1; }
日志: [4f] now f: function f() { return 0; }
日志: [4g] now g: function g() { return 1; }
日志: [5f] now f: function f() { return 0; }
日志: [5g] now g: function g() { return 1; }
日志: [6f] now f: function f() { return 0; }
日志: [6g] now g: function() { return false; }
false
和 chrome 6 的结果只有空格位置的区别。
根据运算符的优先级:先计算[] == ![] 然后在计算g() && 和前边的结果;
至于 [] == ![] 的问题,因为 ![] 等于 false,是个简单值,所以需要把 [] 转换为简单值(toString)。而 [].toString() 的结果是空字符串,所以在 == 的宽松比较下它们相等。
本人测试结果:
* IE 6,7,8: true
* Firefox 3.6.8: true
* Chrome 6, IE9 beta, Safari 5: false
转自:http://lifesinger.org/blog/category/dev/
- 关于函数声明表达式的一道题目
- 一道关于虚函数指针的题目
- 一道关于函数声明与对象定义的笔试题
- 关于继承的一道题目
- 一道关于排序的题目
- 关于fork的一道题目
- 一道关于继承的题目
- 关于函数表达式和函数声明
- 一道关于C++ 的面试题目(继承、构造函数以及析构函数)
- 笔试的一道关于测试的题目
- 关于byte的一道有趣的题目
- 一道关于时间复杂度的数据结构题目
- 一道面试题目,关于this的理解
- 一道关于运用Hashtable的题目
- 一道关于实例化顺序的题目
- 关于腾讯面试的一道题目
- 关于Notify() wait()的一道面试题目
- 关于指针加减的一道题目
- loadrunner关联失败
- 第一篇Crackme破文,第一个keygen
- 如何建立mysql时间戳字段
- http请求的详细过程
- 内存的分频
- 关于函数声明表达式的一道题目
- rip 路由
- 360和QQ
- shell脚本 20101102(二)
- .htaccess rewrite域名到子目录
- Android应用移植到OPhone平台指南
- SecureCRT 复制 Vim 乱码
- linux 安装 vnc
- Mysql安装