[一道题搞蒙你] - js预处理和各种提升

请听题:


var c = 1;

function c(c) {
    console.log(c);
    var c = 3;
}

c(2);

复制代码

运行结果:

// 直接给你报错
TypeError: c is not a function
复制代码

解析:

  • 第一个坑(预处理):

    js语言本身具有预处理机制,js引擎在预处理期对所有声明的变量和函数进行处理,就是先把变量进行声明并读到内存里。也就是收集用var声明的变量信息和函数声明信息。变量和函数的优先顺序:先变量后函数。当变量名和函数名一致时后者会覆盖前者,来个小?:

        function b() { };
        var b ;
        console.log(typeof b)  // function
    复制代码

    看啥看,就是function服不服? 接着再来个小?:

        function b() { };
        var b = 1 ;
        console.log(typeof b)  // number
    复制代码
  • 第二个坑(作用域域预处理):

    js中存在两种作用域,全局作用域函数作用域, 预处理过程中的变量和函数提升都是在作用域上下文内进行。废话不多说,再来吃个?:

        var a = 2  
        function fn() {  
            console.log(a)  
            var a = 3  
        }  
        fn() // undefined
    复制代码

    为什么是undefined呢? 全局作用域和fn函数作用域内变量、函数分别进行提升。当fn调用时,外层全局作用域的变量a值未2但是这并没什么卵用,因为在fn的函数作用域内也声明了一个变量a,函数作用域内的变量a也会进行提升,当console.log(a)语句执行的时候,fn作用域内的a变量声明但未赋值,所以输出undefined

  • 回到本文?: 当本文中的例子预解析各种提升完成以后,实际执行时的环境是这样的:

        var c ;
        c = function (c) {
            console.log(c);
            var c = 3;
        };
        c = 1 ;
        
        c(2);   // TypeError: c is not a function
    复制代码

补充:

es6+中,还存在块作用域 ,结合letconst等关键字进行变量的生命能够避免很多问题,在本文中不再进一步讨论,有兴趣的同学可以去查一下。话又说回来,如果你没在ES6 前踩过这些坑,其实很难理解ES6 为什么会那么搞。

转载于:https://juejin.im/post/5bbec3fa6fb9a05d232880b3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值