天天看点

es6---let和const

在es6之前,只有全局作用域与函数作用,变量只能用var来声明。而es6中新增了块级作用域,变量可以用let、const来声明变量。

内容概述

•var和let const的区别

•块级作用域与函数声明

1、var和let const的区别

1.1:let const声明的变量只在代码块作用域内有效,块作用域就是在大括号{}范围内有效;而var声明的变量在函数作用域或者全局作用域内有效,并没有块级作用域的概念。

if (true) {
    let a = 1;
   console.log(a); // 1
}
console.log(a); // ReferenceError: a is not defined,变量a只在if代码块内有效      
if (true) {
     var a = 1;
 }
 console.log(a); // 1      
var a = [];
for(var i = 0 ;i < 10; i++) {
    a[i] = function () {
        console.log(i);
    }
}
a[6](); // 10,a[i]的值存的是一个函数对象,a[i]对应的函数在执行的时候,需要拿到i的值。而在这里,var声明的变量是一个全局变量,每次循环都会改变全局作用域中的i值,a[i]对应的函数执行的时候拿到的是同一个i值,当a[i]对应的函数执行的时候,循环已经执行完毕,i值已经变为10。      
var a = [];
for(let i = 0 ;i < 10; i++) {
    a[i] = function () {
        console.log(i);
    }
}
a[6](); // 6,let声明的变量会绑定一个块级作用域,每次循环都会产生一个i值,且只在本轮循环中有效,js引擎会记住上轮循环的i值,下次循环的i值会使用上次循环的i进行初始化。      

1.2 :let和const声明的变量不存在变量提升,而var声明的变量存在变量提升。

变量提升:就是在变量声明前可以访问变量,值为undefined。

console.log(a); // undefined,var声明的变量会提升到全局作用域或者函数作用域的头部

console.log(b); // ReferenceError,暂时性死区,{}代码块中存在let和const的变量的话,let和const声明的变量会绑定当前块作用域,不允许在变量声明之前使用

typeof b; // ReferenceError,暂时性死区

var a = 1;

let a = 2; // SyntaxError: Identifier 'a' has already been declared,let和const不允许同一个作用域中重复声明变量

let b = 2;

1.3:const声明的是一个常量,不可以更改,否则报错。const命令的本质是保证变量指向的内存地址不可以改变,对于简单类型(Number,String,Boolean)而言,变量的值就是栈区中保存的值;对于对象而言,变量的值是栈区中保存的一个指向堆区的指针。

补充堆栈数据结构:如下图;

es6---let和const

 js中数据在堆栈中存储情况: 如下图;

es6---let和const
const a = 1;
a = 2; // TypeError
const obj = {
    name: 'es6',
    age: 5
};
const arr = [ 1, 2, 3];
obj.age = 4 ;
arr.push(4);
console.log(obj); // {name: "es6", age: 4}
console.log(arr); // (4) [1, 2, 3, 4]
obj = {
    name: 'es5'
}; // TypeError
arr = ['a', 'b', 'c']; // TypeError      

2、块级作用域与函数声明

首先,es5规定,函数只能在顶层作用域和函数作用域中声明,不能在块级作用域中声明。但是,浏览器并没有遵守这个规定,块级作用域中声明的函数实际上都能运行,并不会报错。在js中创建函数有函数声明和函数表达式两种方式,而函数声明存在函数提升,函数会被提升到所在作用域的头部位置。函数表达式不存在变量提升。

foo(); // foo,函数声明提升
bar(); // bar is not a function
if(true) {
    function foo() {
        console.log('foo');
    }
    var bar = function () {
        console.log('bar');
    }
}
bar(); // bar

// 实际运行代码如下:
function foo() {
    console.log('foo');
}
var bar;
foo(); // foo
if(true) {
    bar = function () {
        console.log('bar');
    } 
}
bar(); // bar        

在es6的浏览器环境中,块级作用内的函数声明类似于var,会被提升到所在的块级作用域的头部。es6的非浏览器环境中,块级作用域中函数声明当作let处理即可。下面是es6的浏览器环境中块级作用域中函数声明的例子:

if(false) {
    function f() {
        console.log('foo');
    }
}
f(); // f is not a function

// 实际运行的代码如下:
var f;
if(false) {
    function f() {
        console.log('foo');
    }
}
f(); // f is not a function