let和const====均参考阮大神的es6入门

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了let和const====均参考阮大神的es6入门相关的知识,希望对你有一定的参考价值。

 

// 解构复制
// let [foo,[[bar],baz]] = [1,[[2],3]];
// console.log(foo);//1
// console.log(bar);//2
// console.log(baz);//3

 

// let [,,third] = ["foo","bar","baz"];
// console.log(third)//baz;

 

// let [x,,y] = [1,2,3];
// console.log(x+"---"+y)//1---3

 

// let [head,...tail] = [1,2,3,4];
// console.log(Array.isArray(tail))//证明是数组
// console.log(head+"--"+tail)//1--2,3,4
// console.log(typeof tail)//object

 

// let [x, y, ...z] = [‘a‘];
// 解构不成功,变量的值就等于undefined
// console.log(x+"---"+y+"---"+z)//a---undefined---[]

 

// 如果等号的右边不是数组(或者严格地说,不是可遍历的结构,参见《Iterator》一章),那么将会报错。
// 报错
// let [foo] = 1;
// let [foo] = false;
// let [foo] = NaN;
// let [foo] = undefined;
// let [foo] = null;
// let [foo] = {};

 

// 只要某种数据结构具有Iterator(迭代)接口,都可以采用数组形式的解构赋值。
// Generator函数(生产者?)
// function* fibs() {
// var a = 0;
// var b = 1;
// while (true) {
// //0 1 1 2 3 5
// yield a;
// //1,1 1,2 2,3 3,5 5,8
// [a, b] = [b, a + b];
// }
// }

 

// var [first, second, third, fourth, fifth, sixth] = fibs();
// console.log(first)//0
// console.log(second)//1
// console.log(third)//1
// console.log(fourth)//2
// console.log(fifth)//3
// console.log(sixth)//5

 

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

 

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

 

// let不像var那样会发生“变量提升”现象。所以,变量一定要在声明后使用,否则报错。
// console.log(foo); // 输出undefined
// //console.log(bar); // 报错ReferenceError

 

// var foo = 2;
// //let bar = 2;// 报错ReferenceError

 

// 只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
// var tmp = 123;
// 存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。
// if (true) {
// tmp = ‘abc‘; // ReferenceError
// let tmp;
// }

 

// var tmp = 123;
// if (true) {
// let tmp;
// tmp = ‘abc‘; //不报错
// }
// ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

 

// 在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称TDZ)。
// if (true) {
// // TDZ开始
// //tmp = ‘abc‘; // ReferenceError
// //console.log(tmp); // ReferenceError

 

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

 

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

 

// “暂时性死区”也意味着typeof不再是一个百分之百安全的操作。
// typeof x; // ReferenceError
// let x

 

// 作为比较,如果一个变量根本没有被声明,使用typeof反而不会报错。
//console.log(typeof y)//undefined

 

// 调用bar函数之所以报错(某些实现可能不报错),是因为参数x默认值等于另一个参数y,而此时y还没有声明,属于”死区“。如果y的默认值是x,就不会报错,因为此时x已经声明了。
// function bar(x = y, y = 2) {
// return [x, y];
// }

 

// bar(); // 报错

 

// function bar(y = x, y = 2) {
// return [x, y];
// }

 

// bar(); // 报错

 

// function bar(x = 2, y = x) {
// return [x, y];
// }
// bar(); // [2, 2]

 

// 暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

 


// 不允许重复声明
// 报错
// function () {
// let a = 10;
// var a = 1;
// }

 

// // 报错
// function () {
// let a = 10;
// let a = 1;
// }

 

// function func(arg) {
// let arg; // 报错
// }

 

// function func(arg) {
// {
// let arg; // 不报错
// }
// }

 


// 变量提升
// ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。

 

// 第一种场景,内层变量可能会覆盖外层变量。
// var tmp = new Date();

 

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

 

// f(); // undefined

 

// var tmp = new Date();

 

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

 

// f(); // undefined
// 上面代码中,函数f执行后,输出结果为undefined,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。
// 第二种场景,用来计数的循环变量泄露为全局变量
// var s = ‘hello‘;
// for (var i = 0; i < s.length; i++) {
// console.log(s[i]);
// }

 

// console.log(i); // 5

 

// var s = ‘hello‘;
// for (let i = 0; i < s.length; i++) {
// console.log(s[i]);
// }
// console.log(i); // i is not defined

 

// 这表示外层代码块不受内层代码块的影响
// function f1() {
// let n = 5;
// if (true) {
// let n = 10;
// }
// console.log(n); // 5
// }
// f1()//5

 


// 互不影响
// {{{{
// let insane = ‘Hello World‘;
// {let insane = ‘Hello‘;
// console.log(insane)//Hello
// }
// console.log(insane)//Hello World
// }}}};

 

// 块级作用域的出现,实际上使得获得广泛应用的立即执行匿名函数(IIFE)不再必要了。
// IIFE写法
// (function () {
// var tmp = ...;
// ...
// }());

 

// // 块级作用域写法
// {
// let tmp = ...;
// ...
// }

 

// ES5严格模式
// ‘use strict‘;
// if (true) {
// function f() {}
// }
// 报错

 

// ES6严格模式
// ‘use strict‘;
// if (true) {
// function f() {}
// }
// 不报错

 

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

 

// f();
// }());

 

// ES6的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。
// ‘use strict‘;
// if (true) {
// function f() {}
// }

 

// // 报错
// ‘use strict‘;
// if (true)
// function f() {}

 

// const声明一个只读的常量。一旦声明,常量的值就不能改变。
// const foo = {};
// foo.prop = 123;

 

// foo.prop
// 123

 

//foo = {}; // TypeError: "foo" is read-only

 

// 常量foo储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性。

 

// const a = [];
// a.push(‘Hello‘); // 可执行
// a.length = 0; // 可执行
// a = [‘Dave‘]; // 报错

 

// 如果真的想将对象冻结,应该使用Object.freeze方法
// const foo = Object.freeze({});

 

// // 常规模式时,下面一行不起作用;
// // 严格模式时,该行会报错
// foo.prop = 123;
// 常量foo指向一个冻结的对象,所以添加新属性不起作用,严格模式时还会报错。

 

// ES6为了改变这一点,一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从ES6开始,全局变量将逐步与顶层对象的属性脱钩。

 

// var a = 1;
// // 如果在Node的REPL环境,可以写成global.a
// // 或者采用通用方法,写成this.a
// window.a // 1

 

// let b = 1;
// window.b // undefined

 

以上是关于let和const====均参考阮大神的es6入门的主要内容,如果未能解决你的问题,请参考以下文章

读阮一峰老师 es6 入门笔记 —— 第一章

ES6之let(理解闭包)和const命令

js 笔记读阮一峰老师 es6 入门笔记 —— 第一章

ES6 阮一峰阅读学习

ES6必知必会 —— 变量声明和结构赋值

ES6 之 let / const