专栏首页coding个人笔记我理解的JavaScript预编译

我理解的JavaScript预编译

JavaScript是一门单线程,解释型,弱类型的动态语言,解释一行执行一行。

JavaScript执行过程首先先语法分析,就是分析一遍代码有没有语法错误,解析期间不会执行代码。接着就开始预编译,预编译完了就开始一行一行执行代码。

预编译过程会创建两个对象,一个是全局的Global Object对象,简写GO,另一个是函数的Activation Object对象,简写AO。两个只是作用域不同,创建步骤是一样的。

预编译大概步骤:

创建AO、GO对象

找形参和变量声明,作为属性名,值为undefined

统一实参和形参

找函数声明,赋值函数体

说的抽象了,我们以一个函数为例:

function fn(a) {
  console.log(a);
  var a = 1;
  console.log(a);
  function a() {};
  console.log(a);
  var b = function () {};
  console.log(b);
  function c() {}
}
fn(3);

创建AO = {}

把形参和变量声明作为属性名和赋值undefined

AO  =  {
a: undefined,//参数a var a function a
b: undefined,//var b
c :undefined,//function c
}
统一形参和实参
AO  =  {
a: 3,
b: undefined,//var b
c :undefined,//function c
}

找函数声明,赋值函数体

AO  =  {
a: function a(){},
b: undefined,//var b
c: function c(){},
}

接着就是一行一行执行了:

function fn(a) {
  console.log(a);
  var a = 1;
  console.log(a);
  function a() {};
  console.log(a);
  var b = function () {};
  console.log(b);
  function c() {}
}
fn(3);
AO  =  {
  a: function a(){},
  b: undefined,
  c: function c(){},
}

当执行第一个打印的时候,打印出function,然后var a = 1的时候,声明已经声明过了,其实就a = 1,所以第二个打印是1,到了声明函数a的时候已经是声明过的,再打印也是1,至于b和c就不用多说了。最后结果就是f a(){}、1、1、f(){}。

其实可以记住几个点,函数声明是整体提升,变量声明只是声明提升。还有,如果一个变量没有声明,那么默认就是window的:

(function fn() {
  var a = b = 10;
}());
console.log(b);//10
console.log(a);//err

b没有直接var声明,那么就是全局window的,所以b能打印,a就会报错。

有个点要注意,JavaScript在预编译阶段, 会解释函数声明, 但却会忽略表式。比如一个自执行函数:

(function fn() {
}())

当执行到有()的时候,JavaScript会去对这个表达式求解得到返回值,返回的是一个函数且有(),所以直接执行了,其它的自执行函数原理都是这样的,都是通过表达式。函数转换为表达式的方法并不一定要靠分组操作符(),我们还可以用void操作符,!操作符+操作符等等。

+function () {}()
void(function () {alert(0)}())
console.log(function () {alert(0)}())

这些表达式都可以立即执行函数,就算+号得到的最终结果是NaN,但是在隐式转换之前却要先执行函数。

函数参数你可以看作在函数里面隐式的声明了一个变量a:

function fn(a) {
  var a;
  console.log(a);//3
}
fn(3)

而且函数参数里面在预编译过程中,会形成一个临时作用域,在预编译完了之后会消失:

function fn(a, b = function () {a = 5}) {
  console.log(a);//3
  b();
  console.log(a);//3
}
fn(3)

(a, b = function () {a = 5})这是一个临时的作用域,这里面的参数a就算改变了也影响不到原来的参数a。只有在参数作用域里面才有效果:

function fn(a, b = (function () {a = 5})()) {
  console.log(a);//5
  console.log(a);//5
}
fn(3)

(完)

本文分享自微信公众号 - coding个人笔记(gh_2ce38b49dae1),作者:wade

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 链式调用this

    jQuery在JavaScript库中的一哥地位是不可撼动的,虽然随着这几年框架的崛起和一些大平台移除了jQuery的依赖,但不可否认jQuery还是前端开发必...

    wade
  • Web直传OSS

    最近公司需求,前端直接传图片到OSS,一般我们都是传到服务器后台,然后由后台存储。这样其实有一些缺点,OSSAPI上面说:

    wade
  • JavaScript深拷贝和浅拷贝

    在JavaScript中操作数据的时候,基础数据类型还好,不管是我们怎么赋值修改都不会有什么问题,但是如果我们操作的是数组或者Object,那很容易出现修改了一...

    wade
  • 探究{ a = 1; function a(){} }和{ function b(){}; b = 1 }

    相信大部分人都了解了,这里再重复啰嗦一下。js是解析执行的,变量提升是js中执行上下文的工作方式。变量声明和函数声明在编译阶段会被提前。

    lhyt
  • 意译:自调用函数表达式

    一、写在前面   本文将一如既往地遵循从自身理解出发,而非100%按原文逐句翻译的方式进行“伪翻译”,若有谬误请各位指正,谢谢!! 二、介绍   IIFE(th...

    ^_^肥仔John
  • 20180708_ARTS_week02

    Add Two Numbers You are given two non-empty linked lists representing two non-ne...

    Bob.Chen
  • 从Generator到Async function

    为什么说Async function是从Promise,Generator一路走来的?

    ayqy贾杰
  • es6之深入理解promise对象

    连小壮
  • 深入理解es6的promise

    我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?inv...

    连小壮
  • mui 百度语音识别转换文字

      用mui混合开发的APP,现有一个功能需求就是语音转换成文字,并把语音进行保存。对此考虑两种选择讯飞和百度。最终选择了百度语音。

    kmonkey

扫码关注云+社区

领取腾讯云代金券