1-let/const

一、let 声明的变量只在它所在的代码块有效 --(for循环的计数器)  

  1、for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域

  2、不存在变量提升 <==>  var命令会发生“变量提升”现象

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

  4、不允许重复声明

  5、块级作用域 { } 

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6

疑问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

二、块级作用域 { } 

  1、ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。

  2、ES6 引入了块级作用域,明确允许在块级作用域之中声明函数,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。

// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }

(function () {
  if (false) {
    // 重复声明一次函数f
    function f() { console.log('I am inside!'); }
  }

  f();
}());
// Uncaught TypeError: f is not a function

ES6 在附录 B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。
1、允许在块级作用域内声明函数。
2函数声明类似于var,即会提升到全局作用域或函数作用域的头部3、同时,函数声明还会提升到所在的块级作用域的头部。

实际运行代码如下:
// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }
(function () {
  var f = undefined;
  if (false) {
    function f() { console.log('I am inside!'); }
  }

  f();
}());
// Uncaught TypeError: f is not a function

三、const

  1、const声明一个只读的常量。一旦声明,常量的值就不能改变,所以一旦声明,就必须立即初始化

  2、不存在变量提升

  3、块级作用域

  4、暂时性死区

  5、不可重复声明

  ***const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动,

  对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。

  但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),

  至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心

const foo = {};

// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123

// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only

  如果真的想将对象冻结,应该使用 Object.freeze 方法

const foo = Object.freeze({});

// 常规模式时,下面一行不起作用;
// 严格模式时,该行会报错
foo.prop = 123;

四、六种声明方式

  1、var

  2、function

  3、let

  4、const

  5、import

  6、class

五、顶层对象的属性

  1、浏览器 -- window

  2、Node -- global

原文地址:https://www.cnblogs.com/slightFly/p/11867307.html