0基础学习,深夜写文章,励志进大厂系列,第2天:JS预编译

如果你不懂JS预编译,那你眼里的代码和V8引擎眼里的代码,可能不是同一份代码。

你问我为什么?那好,看一份代码。

css 复制代码
console.log(a)//输出undefined
var a = 10;

那你可能要说了,我知道输出的是undefined,这不就是个简单的变量提升嘛!

对了,确实是因为变量提升,那我问你,什么是变量提升??嗯?Looking in my eyes

再看这份代码,那我问你输出的是什么?

php 复制代码
var a = 1
 function fn() {
     var a = 2
     console.log(a)
}
fn()

那你可能会说,由内向外查找嘛!输出2,秒了!

你是对的(一脸肯定!)那我考考你,为什么会由内向外查找??嗯?(狗头)Looking in my eyes

再看一份代码,请问,输出的是什么?嗯?

php 复制代码
var a = 1
function fn() {
     var a = 2
     function a() { }
     console.log(a)
}
fn()

如果此时你都知道了,请允许我叫你一声老前辈,不知道的UU请允许我开始表演

这份代码,在JS眼里长什么样呢?

css 复制代码
console.log(a)//输出undefined
var a = 10;

长这样:

less 复制代码
var a;//找声明
console.log(a)//执行语句,输出undefined
a = 10;//执行语句

为什么会这样,先说结论:

编译全局 -> 执行全局 -> 编译函数 -> 执行函数 -> 编译函数 -> 执行函数 -> ...

函数体编译过程(全局差不多)

1、创建执行上下文对象(强调是对象)

2、找形参和变量声明,将变量和形参名作为上下文对象的属性名,值为undefined

3、将实参值和形参统一

4、在函数体里面找函数声明,函数名作为上下文对象的属性名,值为函数体

图解JS预编译

第一份代码:

css 复制代码
console.log(a)//输出undefined
var a = 10;

首先,JS执行引擎会找到当前作用域所有的变量的声明后,再找到执行语句,执行语句的复值等操作。所以,JS在全局作用域找到var a=undefined,发现没有变量声明语句后,就开始了从上往下执行语句,很明显,console.log(a)a = 10先执行。所以就有了输出为undefined,如果你要是问我,a的值最终是多少,那确实是10

第二份代码:

直接上图:

php 复制代码
var a = 1
 function fn() {
     var a = 2
     console.log(a)
}
fn()

首先,在全局变量,JS发现了两个声明语句,先是var a=undefined,再是fn=function(){},找完全局的声明语句后,就开始找全局作用域的执行语句,所以它找到了a=1,所以此时a=1,然后他又发现了fn(),所以,这时,JS引擎要处理fn这个函数。在函数fn里,JS引擎同样先找声明语句,它找到了var a = undefined,然后发现没有了,就先找到执行语句a=2,再执行console.log(a)。因此就有了结论:从内向外逐层查找

第三份代码:

我们可以看到,这与第二份代码的区别就在于多了一行function a() { },那输出的是什么?首先,肯定是2[Function: a]之中的一个。

php 复制代码
var a = 1
function fn() {
     var a = 2
     function a() { }
     console.log(a)
}
fn()

只需要知道:function a() { }是声明语句,那问题就迎刃而解了。嗯?真的没有问题嘛?你就不想问我为什么声明函数a会覆盖变量a?注意,在JS里,它们都是对象,对象里的属性能重复吗?好了,解释完毕。

小练习,附带答案,各位观众别走!!!!

javascript 复制代码
function fn() {
    console.log(a)
    var a = 100
    console.log(a)
    function a() { }
    var b = function () { }
    console.log(b)
    function c() { }
    var c = a
    console.log(c)
}

fn()

所以输出为:

ini 复制代码
function fn(a, b) {
    console.log(a);
    c = 0
    var c;
    a = 3
    b = 2
    console.log(b);
    function b() { }
    console.log(b);
}
fn(1)
javascript 复制代码
global = 100
function fn() {
    console.log(global)
    global = 200
    console.log(global)
    var global = 300
}

fn()
var global

好了,如果你已经理解了,那么恭喜你知道了什么叫做JS的预编译。写作不易,恳请各位观众老爷点个赞。

相关推荐
SuperEugene22 分钟前
Vue3 组合式函数(Hooks)封装规范实战:命名 / 输入输出 / 复用边界 + 避坑|Vue 组件与模板规范篇
开发语言·前端·javascript·vue.js·前端框架
cmd25 分钟前
JS深浅拷贝全解析|常用方法+手写实现+避坑指南(附完整代码)
前端·javascript
进击的尘埃26 分钟前
AbortController 实战:竞态取消、超时兜底与请求生命周期管理
前端·javascript
张一凡9327 分钟前
我用 Zustand 三年了,直到遇见 easy-model...
前端·javascript·react.js
张元清27 分钟前
React 拖拽:无需第三方库的完整方案
前端·javascript·面试
zhensherlock38 分钟前
Protocol Launcher 系列:Microsoft Edge 浏览器唤起的优雅方案
javascript·chrome·microsoft·typescript·edge·github·edge浏览器
英俊潇洒美少年1 小时前
Vue3 中 watch的 flush 选项(默认无/`post`/`sync`)的区别
前端·javascript·vue.js
D_C_tyu1 小时前
HTML | 结合Canvas开发具有智能寻路功能的贪吃蛇小游戏实战详解
javascript·算法·游戏·html·bfs
Jay-r1 小时前
樱花雨特效 WebGL实现 短视频同款浪漫视觉效果(附源码下载)
开发语言·javascript·ecmascript·编程·webgl·代码·樱花雨
凤山老林1 小时前
Js如何实现一个抽奖程序
前端·javascript·vue.js