美文网首页
块级作用域之LET CONST

块级作用域之LET CONST

作者: 刘越姐姐啊 | 来源:发表于2019-10-28 09:18 被阅读0次

一、全局作用域

用 var 在全局(函数外)声明的所有变量,都具有全局作用域,即: 网页中所有脚本和函数均可使用。

(1)最外层函数和在最外层函数外面定义的变量拥有全局作用域,例如:

var aName="哈哈";
function doSomething(){
    var bName="嘿嘿";
    function innerSay(){
        alert(bName);
    }
    innerSay();
}
alert(aName); //哈哈
alert(bName); //脚本错误
doSomething(); //嘿嘿
innerSay() //脚本错误

(2)所有末定义直接赋值的变量自动声明为拥有全局作用域,例如:

function doSomething(){
    var aName="哈哈";
    bName="嘿嘿";
    alert(aName);
}
doSomething(); //哈哈
alert(bName); //嘿嘿
alert(aName); //脚本错误

二、局部作用域

局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部,例如下列代码中的bName和函数innerSay都只拥有局部作用域。在函数中用 var 声明的所有变量,都是函数的局部变量,具有局部作用域,即:变量只能在函数内部使用,函数外部是不行的

function doSomething(){
    var bName="嘿嘿";
    function innerSay(){
        alert(bName);
    }
    innerSay();
}
alert(bName); //脚本错误
innerSay(); //脚本错误

三、存在的问题

在ES5中,只有全局作用域和函数作用域。这会导致函数作用域覆盖了全局作用域;亦或者循环中的变量泄露为全局变量。

(1)内层变量可能覆盖外层变量(变量提升)

 var tmp = new Date();

 function f(){
   console.log(tmp);
   var tmp = "hello";
 }
 
 f();//undefined

 var tmp = new Date();

 function f(){
   var tmp;
   console.log(tmp);
   tmp = "hello";
 }
 
 f();//undefined

(2)用来计数的循环变量泄露为全局变量

for (var i = 0; i < 10; i++) {    
   console.log(i);    
}    
console.log(i);  // 10 

四、块级作用域

ES6中新增了块级作用域,块级作用域由 { } 包括,if语句和for语句里面的{ }也属于块级作用域。ES6可以使用let关键字或者const关键字来实现块级作用域。let或const声明的变量只在let或const命令所在的代码块{}内有效,在{}之外不能访问。

(1) 允许块级作用域任意嵌套,外层作用域无法读取内层作用域的变量

if(true){
    let a = 10;
    var b = 1;
    if(true){
        let c = 20;
        console.log(a); //10
        console.log(b); //1
    }
    console.log(c)// ReferenceError: c is not defined.
}

(2) 内层作用域可以定义外层作用域的同名变量

if(true){
    let a = 10;
    var b = 30;
    if(true){
        let a = 20;
        var b = 40;
        console.log(a);//20
        console.log(b);//40
    }
    console.log(a);//10
    console.log(b);//40
}

五、块级作用域之LET CONST

(1)ES6 新增了let和const命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let和const命令所在的代码块内有效。

if(1){
    var a = 100;
    let b = 10;
}

console.log(a); // 100
console.log(b)  // 报错:b is not defined  ===> 找不到b这个变量

for(let i =0; i<arr.length; i++){
}
console.log(i) //ReferenceError: i is not defined

    var arr = [];
    for (var i = 0; i < 10; i++) {
        arr[i]=function(){
            console.log(i);
        }
    }
    arr[2]();       //输出的是10    

    var arr = [];
    for (let i = 0; i < 10; i++) {
        arr[i]=function(){
            console.log(i);
        }
    }
    arr[2]();       //输出的是2

(2)不存在变量提升,let和const命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。

console.log(a); // undefined  ===>  a已声明还没赋值,默认得到undefined值
var a = 100;

console.log(b); // 报错:b is not defined  ===> 找不到b这个变量
let b = 10;

console.log(c); // 报错:c is not defined  ===> 找不到c这个变量
const c = 10;

(3)同一作用域下let和const不能声明同名变量,而var可以

var a = 100;
console.log(a); // 100

var a = 10;
console.log(a); // 10

let a = 100;
let a = 10;

//  控制台报错:Identifier 'a' has already been declared  ===> 标识符a已经被声明了。

(4)const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。但是这并不意味着不可变,如果声明的是复合类型数据,可以修改其属性

const a = 100; //声明后不能再修改

const list = [];
list[0] = 10;
console.log(list);  // [10]

const obj = {a:100};
obj.name = 'apple';
obj.a = 10000;
console.log(obj);  // {a:10000,name:'apple'}

(5)暂时性死区(temporal dead zone):只要块级作用域内存在let和const 命令,它所声明的变量就“定”(binding)这个区域,不再受外部的影响。

var tmp = 123;

if (true) {
   tmp = 'abc'; // ReferenceError
   let tmp;
}

上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。

ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

if (true) {
  // TDZ开始
  tmp = 'abc'; // ReferenceError
  console.log(tmp); // ReferenceError

  let tmp; // TDZ结束
  console.log(tmp); // undefined

  tmp = 123;
  console.log(tmp); // 123
}

(6)用let和const声明的变量不会挂载到顶层对象

const a="aa";
console.log(window.a);// undefined

var b="bb";
console.log(window.b);// bb

window.a = 1;
var a = 2 ;
console.log(a);         // 2
console.log(window.a);  // 2

window.b = 1;
let b = 2 ;
console.log(b);         // 2
console.log(window.b);  // 1

六、VAR LET CONST的总结

(1)var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问,不初始化出现undefined,不会报错。

(2)let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问

(3)const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改,如果声明的是复合类型数据,可以修改其属性

相关文章

  • ES6

    ①const和let var 只有 全局作用域 和 函数作用域 没有块级作用域 { }let 、 const...

  • let 和 const、解构赋值

    let 和 const 块级作用域 let 和 const 声明的变量,只在块级作用域有效(大括号包裹的部分就是块...

  • ES6学习

    1、 var let const var是函数作用域let和const是块级作用域,!const是常量,不能改变。...

  • ES6

    let const let const 没有变量提升let 块级作用域const 常量 模板语言, restfu

  • ES6新特性

    块级作用域let和const let声明变量,const声明常量;都是块级作用域 模板字符串 拼接字符串 用${}...

  • ES6语法--let和const

    1:let和const:作用域,全局作用域,函数作用域以及块级作用域(es6)。 let声明的变量只在块级作用域内...

  • ES 6 新特性列表

    作用域块级作用域块级变量 let块级常量 const 箭头函数sum = (a, b) => a + bnums....

  • ES6笔记

    let&const 1、新增块级作用域2、let -- 作用于 块级作用域3、const声明一个只读的常量。一旦...

  • 高频前端面试题汇总之JavaScript篇-ES6

    ES6-基础 1.let、const、var的区别 (1)块级作用域 块作用域由 { }包括,let和const具...

  • 《JS原理、方法与实践》- ES6新增语法

    let 和const var定义的变量是function级的作用域,let定义的变量属于块级作用域,而const定...

网友评论

      本文标题:块级作用域之LET CONST

      本文链接:https://www.haomeiwen.com/subject/defjyctx.html