当前位置: 首页 > Web前端 > JavaScript

编程题:为什么最后一个1不是5

时间:2023-03-27 10:27:27 JavaScript

前段时间有人邀请我在知乎上回答一个问题:为什么最后一个1不是5?题目如下:console.log(a)if(true){a=1functiona(){}a=5console.log(a)}console.log(a)我第一反应是:undefined,5,5.估计分析的和题主想的一样。如果没有if(true),下面的代码是:console.log(a)a=1functiona(){}a=5console.log(a)console.log(a)那么答案是什么?a(),5,5这说明了两个特征变量,函数提升和函数的权重大于变量。当a没有用var声明时,a=XX默认用var声明变量。函数提升的知识点是:变量会被提升,函数也会被提升,函数提升的优先级高于变量,如下例:console.log(a)console.log(a())vara=1functiona(){console.log(2)}console.log(a)vara=3a=4console.log(a)console.log(a())a(),2,1,4,aisnotafunction回看本题console.log(a)if(true){a=1functiona(){}a=5console.log(a)}console.log(a)if(ture){},形成作用域,锁住piece变量,函数a(){}无法逃逸。也就是说,只要有{}块级标识,函数a(){}就会在块级作用域内,也就是说不会在if的块级作用域下提升(ture){}到全局顶层,但是在if(true){}下,也就是代码执行时:console.log(a)if(true){+functiona(){};一=1;-函数a(){};一=5;console.log(a);}console.log(a)如果在a=1之前打印a,a的值为functiona(){}所以在这道题的全局环境下,没有变量提升,写法第一行console.log(a)中,因为找不到a,所以值为undefined,进入if(true){},functiona(){}函数提升,权重最高,所以之前在块级范围内分配a是functiona(){},而window.a是未定义的。代码执行到functiona(){}后,块级作用域中的a依然为1,但是全局变量a被赋值为1执行到a=5,传统赋值影响块级中的ascope,并且不影响全局变量a,所以打印的第二个console.log(a)是5,第三个console.log(a)是1,那么问题来了,为什么要给全局变量a赋值函数a(){}执行后立即变为1?陷入深思,后来发现云步断山在回答中回答,说是历史原因,为了兼容之前的ES5语法,所以规范规定了函数声明在块级作用域的一些行为,每个浏览器都可以实现它。不一样简单来说,一个函数函数声明在块级作用域中的行为类似于var,会在全局作用域中声明一个同名的变量(即在window上挂一个同名的属性,并且默认值为undefined),因为ES6遇到到达块级作用域时,会根据块级作用域创建一个环境记录来存放当前块级作用域的变量,所以这个函数声明会是提升到块级范围的顶部(不是全局范围的顶部)。ECMA262目录B我们学的JavaScript就是ECMAScript,但是我们在浏览器上运行代码的时候,一定要遵循浏览器的标准。浏览器里面会有一些私货,最经典的就是__proto__,迫使ECMA采用它。也就是说,按照这个man的意思//因为函数a()已经声明了,所以有一个window.aconsole.log(a)if(true){//声明了,但是函数被提升了提升是和作用域相关的,所以提升到这个块级作用域的顶部a=1//块级作用域中的a被赋值为1functiona(){}//原地爆炸,执行完function,theglobalwindow.aAssignedtoainblock-levelscopea=5//ainblock-levelscopeisassignedto5againconsole.log(a)}console.log(a)最奇怪的是执行functiona(){}之后全局的window.a被赋值,是块级作用域中的a。这东西没完没了!!等等,我开玩笑的,如果我在工作或者面试中遇到这种问题,我可能还是解决不了。太奇怪了,这不是考题范围(块级作用域、函数提升、变量提升)。让我们从这篇文章开始。本文参与SegmentFault思维随笔《如何“反杀”面试官?》如果您正在阅读,欢迎您加入。