美团前端二面,读代码题求解

发布于 2022-09-12 04:27:01 字数 208 浏览 42 评论 0

var a = 0;
if (true) {
    a = 1;
    function a() {}
    a = 21;
    console.log(a);
}
console.log(a);

求两次 console 出来的值。

答案是21 1。

本菜鸡想了很久也没想明白第二个为啥是1。。

求大佬解惑 ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

呆头 2022-09-19 04:27:01

21 1 的输出结果不完全正确,在不同的浏览器下结果不同
在safari下结果为21 21
在chrome下结果为21 1

同时ECMAScript规范中说函数声明可以嵌套在条件语句块内,但是其运行的结果依赖于JS解析器的实现,其结果具有不确定性,不推荐在生产环境下使用

Functions can be conditionally declared, that is, a function statement can be nested within an if statement, however the results are inconsistent across implementations and therefore this pattern should not be used in production code. For conditional function creation, use function expressions instead.

在巴黎塔顶看东京樱花 2022-09-19 04:27:01

面试官告诉你为什么了吗?
老实说我怀疑这是个未定义行为,反正我是没找到标准中关于这种情况的说明。

根据结果来分析一下,我觉得根源在于js没有为闭包准备一个关键字。
代码简化一下变成这样:

{
    a = 1;
    function a() {}
    a = 21;
    console.log(a);
}

代码块中有方法定义就会自动产生闭包, 因为有{}的存在它又最多只会提升到这段代码块的最上面, a就变成了这段代码块中的局部变量。

a = 1 给"全局"变量 a 赋值
在方法定义之后的 a=21 其实是给局部变量赋值。

如果代码是这个样子我相信任何人都不会觉得难理解:

var a = 0;
{
  a = 1;
  var a_ = _closure() {};
  a_ = 21;
}

附 v8 的bytecode, node版本:v14.7.0

function test() {
  var a = 0;
  {
    a = 1;
    function a() {}
    a = 21;
    // console.log(a);
  }
  // console.log(a);
}
test();
$ node --print-bytecode --print-bytecode-filter=test test.js
[generated bytecode for function: test (0x02368a073831 <SharedFunctionInfo test>)]
Parameter count 1
Register count 2
Frame size 16
   29 S> 000002368A0743FE @    0 : 0b                LdaZero
         000002368A0743FF @    1 : 26 fb             Star r0
   29 E> 000002368A074401 @    3 : 81 00 00 02       CreateClosure [0], [0], #2
         000002368A074405 @    7 : 26 fa             Star r1
   42 S> 000002368A074407 @    9 : 0c 01             LdaSmi [1]
         000002368A074409 @   11 : 26 fa             Star r1
   69 S> 000002368A07440B @   13 : 26 fb             Star r0
   75 S> 000002368A07440D @   15 : 0c 15             LdaSmi [21]
         000002368A07440F @   17 : 26 fa             Star r1
         000002368A074411 @   19 : 0d                LdaUndefined
  135 S> 000002368A074412 @   20 : aa                Return
Constant pool (size = 1)
Handler Table (size = 0)
Source Position Table (size = 15)
回梦 2022-09-19 04:27:01

ECMAScript5标准里并没有描述“代码块里的函数声明”的行为,具体怎么执行要看引擎行为了,就上面的代码在Chrome和IE里执行结果就不同:

// IE
21
function a() {}

JSLint发现“语句块里声明函数”也会报错的,可以看看解释"Function declarations should not be placed in blocks"

~出这样的面试题说明面试官比较虚

星軌x 2022-09-19 04:27:01

搜了一下块内函数声明,貌似这个可能是答案

空心↖ 2022-09-19 04:27:01
var a = 0       // 这里定义一个全局作用域变量a 并初始化为 0
if (true) {     // 一个简单的if语句,制造一个简单的局部/词法作用域
    a = 1    // js的奇怪设定 没有发现局部变量  那么修改的就是全局作用域的a
    function a() { }  // 声明一个局部变量a 此局部变量a在这一行是一个空函数
    a = 21  // 受上一句影响,js以为 你修改的是新声明的 局部变量a
    console.log(a)    // 打印局部作用域的a (毕竟你已经声明了一个局部变量a)
} // 局部/词法作用域结束
console.log(a)// 打印全局作用域的a

如此解释,可?
image.png

我也同意微软的观点,面试官这样难为人真的好吗

image.png

镜花水月 2022-09-19 04:27:01

非答案,贴个同样坑的代码

var c = [{a:0}];
console.log(c);

c[0].a = 1;
console.log(c)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文