JavaScripe中你所不知道的"变量提升"

我们所知的"变量提升"

  • 经典案例与吐槽

这是每一个js的初学者都接触过的经典案例:

js 复制代码
//我们眼中的代码

console.log(a); //输出为undefined
var a=1;

先打印,后执行?!

居然没有报错!!Σ(゚д゚;)

这反直觉的语言究竟是谁设计的!!!("▔□▔)/

  • 出现了!是"变量提升"!太好了,我们有救了!

网课的老师或是教科书会告诉我们,这是因为发生了"变量提升",变量的声明被提高到当前作用域的顶部了。实际的代码执行逻辑如下:

js 复制代码
//实际上的代码执行逻辑

var a;
console.log(a);
a=1;

于是我们便骂骂咧咧的接受了这个概念,并在脑海里为它添加上一个名为"特殊情况,特殊处理"的标签。

但是,真的这样就好了么?这与在米共代码里写上一万个if分支有什么区别!这是对主包脑容量可耻的浪费!

  • 反叛的号角已然吹响!

这是一个仅靠"变量提升"的思维所解决不了的例子:

js 复制代码
//我们眼中的代码

console.log(a);//输出为函数 a()
var a = 1;
function a() { };

按照"变量提升"的思维,代码的执行逻辑如下

js 复制代码
//"变量提升"思维下,代码执行的逻辑

var a;
console.log(a);//输出为 undefined
a=1;
function a(){};

这是经典的错误,标准的零分!

要解决这个疑问,同学们需要知道究竟是怎样的机制存在,才能知道"变量提升"在这里不管用的原因。

我们所不知的背后机制

  • JaveScript的预编译机制

众所周知,在js代码解释执行前,需要先对代码进行预编译。而js特殊的预编译机制就是导致"变量提升"现象出现的原因。

  • 全局预编译

全局预编译的三个步骤

  1. 创建全局执行上下文 GO对象(Global Object)

  2. 在全局作用域中寻找声明对象的段落,以键值对{对象名:undefined}的形式添加进GO对象中。

  3. 在全局作用域中寻找声明函数的段落,以键值对{函数名:函数体}的形式也添加进GO对象中

在完成以上三个步骤之后才开始解释执行js代码,执行时在全局作用域下调用函数与变量时以GO对象中对应的值为准。

示例:

js 复制代码
//原来的代码

console.log(a);
console.log(b);
var a;
function b(){};

经过预编译后的代码逻辑:

js 复制代码
// 事实上的代码逻辑

GO = {
    a: undefined,
    b: function () { }
}
console.log(GO.a);
console.log(GO.b);

同理对上一部分疑问的解答:

js 复制代码
//我们眼中的js代码

console.log(a);
var a = 1;
function a() { };
js 复制代码
//实际上的执行逻辑:

GO=
{
    a:function (){},
    //函数a加入GO时,函数名与对象名相同,所以将属性名a对应的属性值修改了。
}

console.log(GO.a)//输出为函数 a()

于是我们用全局预编译的过程,成功解释了"变量提升"现象发生的原因,以及该说法的局限性。(=・ω・=)

新人报道

  • 关于文章

本文仅适用于新手,更多是用来记录与分享up的学习历程,如果对初入js编程您很有所帮助,不放给up点上一个小小的赞啦(°▽° )八(°▽°)♪

  • 关于文章可能存在的错误与不严谨处

还望大佬轻喷,如若您在百忙之中指出错误之处,up( ´(00)ˋ )顶礼膜拜

  • 本文对js预编译的过程仅作部分阐述,欲知全貌如何,且听下回分解
  • 关于up

是学生,前端在学,初学者,初踏入前端界(;¬_¬)

相关推荐
尘中客1 小时前
放弃 Echarts?前端直接渲染后端高精度 SVG 矢量图流的踩坑记录
前端·javascript·echarts·前端开发·svg矢量图·echarts避坑
2501_916007472 小时前
网站爬虫原理,基于浏览器点击行为还原可接口请求
前端·javascript·爬虫·ios·小程序·uni-app·iphone
Highcharts.js3 小时前
适合报表系统的可视化图表|Highcharts支持直接导出PNG和PDF
javascript·数据库·react.js·pdf
叫我一声阿雷吧4 小时前
JS 入门通关手册(35):执行上下文、调用栈与作用域链深度解析
javascript·作用域链·js进阶·执行上下文·调用栈·变量提升·闭包原理
Amumu121386 小时前
Js:正则表达式(一)
开发语言·javascript·正则表达式
月光宝盒造梦师8 小时前
Ant Design Ellipsis 中的判断逻辑 isEleEllipsis 方法非常消耗性能
javascript·react·优化
酉鬼女又兒9 小时前
零基础快速入门前端ES6 核心特性详解:Set 数据结构与对象增强写法(可用于备赛蓝桥杯Web应用开发)
开发语言·前端·javascript·职场和发展·蓝桥杯·es6
阿珊和她的猫9 小时前
以用户为中心的前端性能指标解析
前端·javascript·css
叫我一声阿雷吧10 小时前
JS 入门通关手册(36):变量提升、暂时性死区与块级作用域
javascript·变量提升·暂时性死区·tdz·块级作用域· 前端面试
成都渲染101云渲染666610 小时前
跳出“硬件堆砌”陷阱|渲染101如何用技术重构云渲染的专业价值?
java·前端·javascript