ES3 定义变量 和 ES6 定义变量的区别

varlet 的区别,实际上就是 ES3 定义变量 和 ES6 定义变量的区别javascript

  • ES3 定义变量的方式:
    • var
    • function
  • ES6 定义变量的方式:
    • let
    • const
    • class
    • import

ES6 语法相对于 ES3 来讲,最大的特色就是让 JS 变得更加严谨,告别 JS 松散的特色java

思惟导图

1、LETVAR 的区别

一、变量提高方面

  • let 不存在变量提高,因此变量只能在声明定义后使用
  • var 存在变量提高
console.log(n); //=>undefined
var n = 10;
console.log(n); //=>10

console.log(n); //=>Uncaught ReferenceError: Cannot access 'n' before initialization LET不存在变量提高,因此变量只能在声明定义后使用
let n = 10;
console.log(n); //=>10 
复制代码

二、重复声明方面

  • let 是不容许重复声明的
    • 在当前上下文中,无论用什么方式,只要声明了这个变量,都不能基于 let 重复声明了,会报错
    • 是否从新声明,并非在代码执行阶段检测的,而是在词法解析的阶段检测的
  • var 容许重复声明
    • 浏览器自己只识别一次,但不会报错
var n = 12;
var n = 13;
console.log(n); //=>13

let n = 12;
let n = 13;
console.log(n); //=>Uncaught SyntaxError: Identifier 'n' has already been declared

var n = 12;
let n = 13; //=>Uncaught SyntaxError: Identifier 'n' has already been declared

//=>是否从新声明,并非在代码执行阶段检测的,而是在词法解析阶段检测的(词法解析阶段相似于变量提高,在代码尚未执行以前,就发生了,一旦发现有词法错误 SyntaxError ,当前代码都不会再执行了)
console.log('OK');
var n = 12;
let n = 13; //=>报错 可是OK都没有被执行
复制代码

词法解析、词法错误、语法错误

  • 词法解析:词法解析阶段相似于变量提高,在代码尚未执行以前就发生了
  • 词法错误SyntaxError :在词法解析阶段报错,代码尚未执行就报错,一旦发现有词法错误 SyntaxError ,当前代码不会在执行了
  • 语法错误ReferenceError:在代码执行阶段报错,报错前的代码会正常执行

三、全局对象GO方面

在全局上下文中面试

  • let 声明的变量仅仅是全局变量,和GO没什么关系
  • var 声明的变量便是全局变量,也至关于给GO(window)设置了一个属性,并且二者创建映射机制
var n = 10;
console.log(window.n); //=>10

let n = 10;
console.log(window.n); //=>undefined
复制代码

四、暂时性死区问题

  • let能解决基于typeof检测一个没有被声明过的变量结果是"undefined"的暂时性死区问题;
  • var 不能

浏览器有一个BUG(暂时性死区):基于typeof检测一个没有被声明过的变量,并不会报错,结果是"undefined";可是从正确角度来说应该报错才是正常的!浏览器

console.log(typeof n); //=>"undefined"

//=> 若是这个变量在后面会用`LET`声明,则前面再基于`typeof`检测就会报错:不能在声明以前使用
console.log(typeof n); //=>Uncaught ReferenceError: Cannot access 'n' before initialization
let n = 10;
复制代码

五、块级做用域

  • let 在遇到除对象/函数等大括号之外的大括号(例如判断和循环)时,会造成新的块级做用域
  • var 没有块级做用域

2、LET 的块级做用域

在整个JS中,目前为止咱们接触的上下文(做用域)只有两种闭包

  • 全局上下文 EC(G)
  • 函数执行造成的私有上下文 EC(XX)

此时循环体或者判断体等,都不会单独造成私有的上下文,里面的变量都是所在上下文中的变量。函数

if (1 === 1) {
    var n = 10;
    console.log(n); //=>10
}
console.log(n); //=>10

for (var i = 0; i < 5; i++) {...}
console.log(i); //=>5
复制代码

可是在ES6中,提供了一个新的上下文(做用域)形式:块级做用域ui

  • 除对象/函数等大括号之外,若是在其他的大括号中(例如:判断和循环)出现 LET/CONST 等,则会把当前大括号包起来的部分造成一个独立的私有上下文,基于 LET/CONST建立的变量是当前块级做用域域中的私有变量;
if (1 === 1) {
    var n = 10; //=>n是全局变量
    let m = 20; //=>m是当前大括号包起来的 私有的 块级做用域中的 私有变量
    console.log(m); //=>20
}
console.log(n); //=>10
console.log(m); //=>Uncaught ReferenceError: m is not defined


// 相似于造成两个闭包(这里叫作私有的块级做用域)
{
    let x = 10,
        y = 20;
    console.log(x, y);
}
{
    let x = 100,
        y = 200;
    console.log(x, y);
}


for (let i = 0; i < 3; i++) {
    console.log(i); //=>0 1 2
}
console.log(i); //=>Uncaught ReferenceError: i is not defined
复制代码

循环中遇到let/const

  • 图解:
  • 一、建立一个总的块级做用域(父做用域):用来控制循环一轮轮执行
  • 二、每一轮循环都会造成一个新的私有上下文(子做用域):
    • 用来实现循环中要处理的业务需求
    • 会把每一轮循环 i 的值,做为子做用域中的私有变量

和咱们基于 VAR ,每一轮循环都建立一个闭包相似spa

3、LETCONST 的区别

  • CONST声明的变量,不能从新指向新的值(不能修改指针的指向);
let n = 10;
n = 20;
console.log(n); //=>20

const n = 10;
n = 20; //=>Uncaught TypeError: Assignment to constant variable.
console.log(n);
复制代码

一道经典面试题

const 定义的变量值,永远不能被修改了?指针

  • 答:不对
  • 一、const 不能更改指的是:这个变量不能在和其余值进行关联了,也就是不能修改 const 声明变量的指向
  • 二、可是能够在不改变指向的状况下,修改堆内存中的信息(这样也是把值更改了)
  • 三、因此:const 声明的变量,不能修改他的指针指向,可是能够改变其储存值的

例以下面这种状况:code

const obj = {
    name: '金色小芝麻'
};
obj = [10, 20]; //=>Uncaught TypeError: Assignment to constant variable. 
//=> 它不能更改指的是:obj这个变量不能在和其它值进行关联了,也就是不能修改const声明变量的指向

obj.name = '哈哈';
console.log(obj);//=>{name: '哈哈'};
 //=>可是能够在不改变指向的状况下,修改堆内存中的信息(这样也是把值更改了),
 //=> 因此记住:const声明的变量,不能修改它的指针指向,可是能够改变其存储值的
 //=> 因此也就不能说const建立的是一个常量;
复制代码
相关文章
相关标签/搜索