JavaScript作用域

ES5中的作用域

一、全局变量

全局变量有 全局作用域: 网页中所有脚本和函数均可使用
如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量

1.最外层函数和在最外层函数外面定义的变量为全局变量,拥有全局作用域:

var boyName = "刘家军"
function person(){
    var girlName = "袁姮"
    function doSth(){
        console.log(girlName)
    }
    doSth()
}
console.log(boyName) // 刘家军
console.log(girlName) // 报错: girlName is not defined
person()  // 袁姮
doSth() // 报错:doSth is not defined

2.所有末定义直接赋值的变量为全局变量,拥有全局作用域:

function doSth(){
    var boyName = "刘家军"
    girlName = "袁姮"
    console.log(boyName )
}
doSth() // 刘家军
console.log(girlName) // 袁姮
console.log(boyName) // 报错:boyName is not defined

3.所有window对象的属性拥有全局作用域

二、局部变量

变量在函数内声明,变量为局部变量,拥有局部作用域,因为只能在函数内部访问,也称作函数作用域

function person(){
    var boyName = "刘家军"
    function doSth(){
        console.log(boyName)
    }
    doSth()
}
console.log(boyName) // 报错:boyName is not defined
doSth() // 报错:doSth is not defined

三、变量提升

在ES6之前,JS没有块级作用域,只有全局作用域和函数作用域。变量提升即将变量声明提升到它所在作用域的最开始的部分。看代码:

console.log(boyName) // undefined
var boyName = "刘家军"
console.log(boyName) // 刘家军
 
function person() {
  console.log(girlName) // undefined
  var girlName = "袁姮"
  console.log(girlName ) // 袁姮
}
person();

之所以会是以上的打印结果,是由于js的变量提升,实际上上面的代码是按照以下来执行的:

var boyName // 变量提升,全局作用域范围内,此时只是声明,并没有赋值
console.log(boyName) // undefined
boyName = "刘家军" // 此时才赋值
console.log(boyName) // 打印出刘家军
 
function person () {
  var girlName // 变量提升,函数作用域范围内
  console.log(girlName)
  girlName = "袁姮"
  console.log(girlName )
}
person()

ES6中的块级作用域

‘块级作用域’(一对花括号{}即为一个块级作用域)通过新增命令let和const来体现,

let

let和var差不多,都是用来声明变量的。区别就在于:

 1、 let声明的变量只在所处于的块级有效
 2、 let没有‘变量提升’的特性,而是‘暂时性死区’特性

1.let声明的变量只在块级有效

function person(){
    if(true){
        let boyName = "刘家军"
        console.log('in:' + boyName ) // 刘家军
    }
    console.log('out: ' + boyName ) // 报错:boyName is not defined
}

在if外打印boyName ,报错:boyName is not defined
这因为let声明的变量boyName 是属于if内的块级作用域;而不是像var一样

2.let没有‘变量提升’的特性,而却有‘暂时性死区’的特性

var boyName = "刘家军"
function person(){
    console.log(boyName) // 报错:boyName is not defined
    let boyName = "刘家军测试";
};
person()

boyName报错了,说明变量提升了,只是let规定了不能在其声明之前使用而已。我们称这特性叫“暂时性死区”。这一特性,仅对遵循‘块级作用域’的命令有效(let、const)

3.可以解决闭包问题

var arr = [];
for(var i = 0; i < 2; i++){
    arr[i] = function(){
        console.log(i);
    }
}
arr[1]() // 2
var arr = [];
for(let i = 0; i < 2; i++){
    arr[i] = function(){
        console.log(i);
    };
};
arr[1]() // 1

关于闭包 我们明天再仔细讲一讲

const

const命令与let命令一样,声明的变量,其作用域都是块级。
所以const遵循的规则与let相差无二,只是,const是用来声明恒定变量的。
且,用const声明恒定变量,声明的同时就必须赋值,否则会报错。

function test(){
    const num//报错,声明就得赋值
    num = 666
    console.log(num)
}

作用域链的组成

在JS中,函数的可以允许嵌套的。即,在一个函数的内部声明另一个函数

function person(){
  var  boyName = "刘家军";
   function getName(){  // 在person函数内部,声明了函数getName,这就是所谓的函数嵌套。
         var girlName = "袁姮";   
   }
}

对于person来说,person函数在执行的时候,会创建其person函数的作用域, 那么函数getName在创建的时候,会引用person的作用域,如图:
在这里插入图片描述
函数getName在执行的时候,其作用域类似于下面:
在这里插入图片描述
从上面的两幅图中可以看出,函数getName在执行的时候,是会引用函数person的作用域的。所以,像这种函数作用域的嵌套就组成了所谓的函数作用域链。当在自身作用域内找不到该变量的时候,会沿着作用域链逐步向上查找,若在全局作用域内部仍找不到该变量,则会抛出异常。

友情链接: 点击查看所有文章目录

友情链接:点击查看 JavaScript作用域、闭包、this指向系列文章目录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘家军

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值