【踩坑录】Javascript的预解析

在Javascript当中,存在 预解析 这么一个词儿。解释它之前,这得提及到JS引擎的运行机制:

JS引擎运行javascript分为2步:
	1.预解析
	2.代码的顺序执行

由此可见,预解析是JS引擎的首个步骤。

预解析:把js里面所有的 var还有function提升到当前作用域的最前面

预解析的组成部分:
	1.变量预解析(变量提升):把所有涉及var的变量声明提升到当前的作用域最前面,但不提升赋值操作
	2.函数预解析(函数提升) :把所有的函数声明提升到当前作用域的最前面,但不调用函数

为了方便理解,下面举一些例子。

1.变量提升/变量预解析
   // 1)变量提升:将var声明的变量提升到js作用域的最前面,但是不提升变量的赋值
    console.log(name);
    var name = '晓晓';
    
    // 上面的执行顺序:
    // var name; // 变量提升
    // console.log(name); 
    // name = '晓晓';
    

运行结果:
在这里插入图片描述

2.函数提升/函数预解析
   // 2) 函数提升 :把所有的函数声明提升到当前作用域的最前面,但不调用函数
   	f1();
    function f1() {
        console.log("What a nice day!");
    }
    
    // 上面的执行顺序:
    // function f1() { // 函数声明
    //     console.log("What a nice day!");
    // }
    // f1(); // 代码的顺序执行
    

运行结果:
在这里插入图片描述

3.踩坑记录
3.1 坑一知识点:let声明的变量无法进行变量提升,因此必须先声明后使用
// 报错1: name is not defined
 console.log(name);
 name = '元元'; 
 
// 报错2:Cannot access 'name2' before initialization
 console.log(name2);
 let name2 = '淳淳'; 

// 正确:先声明/初始化,后调用
 let name3 = '元淳';
 console.log(name3);

3.2 坑二知识点:var声明的变量被赋值了函数,但是也是属于变量提升
// 报错1: f2 is not a function
 f2();
 var f2 = function() {
     console.log("I'm a music lover.");
 }

 // 其执行的步骤
 // var f2;
 // f2();
 // f2 =  function() {
 // console.log("I'm a music lover.");
 // }
 
// 正确:先声明/初始化,后调用
  var f2 = function() {
        console.log("I'm a music lover.");
  }
  f2();

3.3 坑三:加入作用域链后,变量提升和函数提升综合使用遇到的问题
 // 运行结果: undefined
      var num = 10;
      f1();
      function f1() {
          console.log(num);
          var num = 20;
      }

      // 原因:由于作用域链的原因,根据就近原则,控制台打印的num是f1()里面的num。
      // 此段代码包含了变量提升和函数提升。关键在于变量提升,导致f1()的该num先被声明,然后再依次执行console语句、num的赋值,因此输出的是undefined

      // 解决方法:将num2的初始化语句提前
      // 运行结果:20
      var num2 = 10;
      f2();
      function f2() {
          var num2 = 20;
          console.log(num2);
      }
3.4 坑四:当全局变量和局部变量混入JS预解析当中
 f3();
 console.log('外部:c = ' +  c);
 console.log('外部:b = ' +  b);
 console.log('外部:a = ' +  a); // 这一步报错,导致下面的'+++'输出无法执行 原因:a不是全局变量
 console.log('+++++++++++++++++++++++++++++++');
 function f3() {
     var a = b = c = 9;  // 这部分属于集体声明,相当于var a = 9;b = 9;c = 9; 由于b和c未被定义,因此b和c被当作全局变量,而a被视为局部变量
     console.log('--------------------------');
     console.log('内部:c = ' +  c);
     console.log('内部:b = ' +  b);
     console.log('内部:a = ' +  a);
 }

运行结果:

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我再来更详细地介绍一下JavaScript中的解析。 在JavaScript中,解析是指在代码执行之前,JavaScript引擎会先对代码进行一些处理,包括变量和函数声明的提升。具体来说,解析会将变量和函数的声明提升至代码的顶部,这样在代码执行时就可以直接使用这些变量和函数,而不需要考虑它们的位置。 解析的步骤如下: 1. 将所有的变量声明和函数声明提升到作用域的顶部。 2. 对于重复声明的变量和函数,只保留最后一个声明。 3. 如果变量和函数同名,函数声明会覆盖变量声明。 需要注意的是,解析只会提升变量和函数的声明,而不会提升变量的赋值和函数的定义。例如: ``` console.log(a); // 输出undefined var a = 1; console.log(a); // 输出1 foo(); // 输出hello function foo() { console.log('hello'); } console.log(b); // 报错:ReferenceError: b is not defined ``` 在上面的代码中,变量a和函数foo的声明被提升了,但是变量a的赋值和函数foo的定义不会被提升。而变量b由于没有被声明,所以在代码执行时会报错。 另外,需要注意的是,let和const关键字声明的变量不会进行解析。这是因为let和const关键字声明的变量是块级作用域,只有在声明的位置后面的代码才能访问它们。例如: ``` console.log(a); // 报错:ReferenceError: a is not defined let a = 1; console.log(a); // 输出1 ``` 在上面的代码中,由于变量a使用了let关键字声明,所以在声明之前访问它会报错。 总之,解析JavaScript中的一个重要概念,它能够帮助我们更好地理解JavaScript代码的执行顺序。但是需要注意的是,过度依赖解析会降低代码的可读性和维护性,所以在编写代码时需要尽量避免过多依赖解析

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值