作用域与提升

JavaScript中和C语言、Java这些语言不一样。在JavaScript当中,只存在函数作用域全局作用域,而块级作用域是不存在的。刚刚接触JavaScript的话往往不知道这一点,所以很容易因为这一点在程序中出错。

作用域

JavaScript中作用域分为两种,分别是:

  1. 全局作用域
  2. 函数作用域

其中全局作用域指的是在一个**.js**文件中的作用域。全局作用域往往包含了这些特点:

  • 变量公有化
  • 函数公有化

简而言之就是说全局作用域中的变量和函数在这个**.js都是公有的、可访问的。而函数作用域**则比起它则范围相对狭小一些,特点为:

  • 变量私有化
  • 函数私有化

函数作用域当中的变量和函数都是私有的,任何对变量和函数的修改都只能在这个函数作用域内进行

提升

  • 变量提升
    由于我们上面所说的,JavaScript中没有块级作用域的存在,所以我们的每一个变量都是全局有效,或者是函数内有效。什么意思?我们先来看一下这段代码:
function gg(){
    if(tag !== 'undefined'){
        var tag = 'output!'
        console.log(tag)
    }
}
//输出: output!
复制代码

上面这段代码看似不可能输出output!,但是其实这里发生了变量提升。由于块级作用域不存在,所以代码var tag = 'output!'在运行时发生了如下的情况:

function gg(){
    var tag
    if(tag !== 'undefined'){
        tag = 'output!'
        console.log(tag)
    }
}
//输出: output!
复制代码

即变量tag的定义会被提升到作用域顶部,所以tag的初值为undefined

  • 函数提升
    和变量一样,函数也存在着提升的情况,有两种声明函数的方式:
  1. 函数声明:
function gg(){
    console.log('success')
}
复制代码
  1. 函数表达式:
var gg = function(){
    console.log('success')
}
复制代码

其中只有函数声明能够被提升到作用域顶部,而函数表达式这种形式声明的函数则不能被提升

console.log(f1) //输出 function f1(){}
console.log(f2) //输出 undefined
function f1(){}
var f2 = function(){}
复制代码

与之相关的题目

先来看下这段代码:

for(var i=1;i<6;i++){
    setTimeout(function(){
        console.log(i);
    },1000);
}
//输出结果为: 6 6 6 6 6
复制代码

按照我们本来的意愿应该是让程序隔一秒后输出数字,分别是从15。但是现实是:隔了一秒以后输出5`个6。 前面提到的,js是存在变量提升的,那么由于变量i被提升为全局变量,所以后面输出的变量i其实是同一个i,循环结束后i变为6 那么如何写出自己想要的结果?这里提供几种方法:

  • 方法1:绑定作用域,将关键字var改为let,具体代码为:
for(let i=1;i<6;i++){
   setTimeout(function(){
       console.log(i)
   },1000)
}
复制代码
  • 方法2:运用IIFE(立即执行函数),具体代码为:
for(var i=1;i<6;i++){
   (function(j){
       setTimeout(function(){
           console.log(j)
       },1000)
   })(i);
}
复制代码

总结

JavaScript中只有两种作用域:全局作用域函数作用域。而因为这个原因,在代码中的的函数声明、变量声明都会被提升到作用域顶部

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值