ES6新增—let、const、字符串连接、解构赋值、复制数组

我们在下面的文章中具体讲解ES6时,使用Traceur转码器的直接插入网页的方法来转码ES6
traceur:是由Google出的编译器,可以将ES6编译成ES5
bootstrap:是一个引导程序(与响应式的bootstrap不同)
需要将traceur.js和bootstrap.js下载下来,引入到当前文件中即可
---------------------------------------------------------------------
注意:在使用ES6时,先不用引入任何东西,去测试,
当不支持ES6时,再去引入traceur.js和bootstrap.js对RS6进行转码。
以为现在浏览器已经支持部分ES6功能,有的不需要转码,转码反而错误

1.let定义变量 ——已经被浏览器实现了,不需要编译
以前定义变量:var a=12;
ES6定义变量:let a=12;
代码块:用{}包起来的代码,称为代码块,如if语句,for循环,while循环
let和var定义变量的区别:
1)let即具有函数作用域,又具有代码块作用域
var只有函数作用域
{
let a=12;
alert(a); //正常执行,弹出12
}
alert(a); //报错,a没有定义

{
var b=5;
alert(b); //能正常输出
}
alert(b); //第二次也能够正常输出


2)let不允许在相同作用域内,重复声明同一个变量。
var定义的变量可以重复声明赋值,且后一次会把前一次的值给覆盖
// 报错
function () {
let a = 10;
var a = 1;
}

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

因此,不能在函数内部重新声明参数。
function func(arg) {
let arg; // 报错
}

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

var b=12;
var b=5; //正常,后一次把前一次的给覆盖
所以由上面的区别可以看出,let才更接近其他语言的变量

3)var存在变量提升,即变量可以在声明之前使用,值为undefined
let不存在变量提升,它所声明的变量一定要在声明后使用,否则报错
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;

// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;

补充:
1.在代码块内,使用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
}
2.只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}


let的应用:
封闭空间:
之前实现封闭空间的方法:
(function(){
var a=12; //这里的a相当于局部变量
alert(a);
})();
现在使用let就相当于上面的封闭空间了,更加方便,清晰
{
let a=12;
alert(a);
}

例如解决i的问题:
window.onload=function(){
var aBtn=document.getElementsByTagName('input');
for(var i=0;i<aBtn.length;i++){
aBtn.onclick=function(){
alert(i); //这里并不会实现弹出0,1,2
}
}
}

window.onload=function(){
var aBtn=document.getElementsByTagName('input');
for(var i=0;i<aBtn.length;i++){
(function(i){
aBtn.onclick=function(){
alert(i); //使用封闭空间进行解决,弹出0,1,2
}
})(i);
}
}

window.onload=function(){
var aBtn=document.getElementsByTagName('input');
for(let i=0;i<aBtn.length;i++){
aBtn.onclick=function(){
alert(i); //使用let的块级作用域的特点,代替封闭空间
}
}
}
-----------------------------------------------------------------
for循环中的i问题:
下面的代码使用var,最后输出的是10。
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
上面代码中,变量i是var声明的,在全局范围内都有效。所以每一次循环,新的i值都会覆盖旧值,导致最后输出的是最后一轮的i的值。

如果使用let,声明的变量仅在块级作用域内有效,最后输出的是6。
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

另外,for循环还有一个特别之处,就是循环语句部分是一个父作用域,而循环体内部是一个单独的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
上面代码输出了3次abc,这表明函数内部的变量i和外部的变量i是分离的。


总结:块级作用域其实就是匿名函数立即调用

--------------------------------------------------------------------------------

2.const定义常量
特点:
1)不能重复声明(一旦定义就不能修改),且定义时就要给初始值
因为以后再也不能赋值了,所以声明的时候一定要有值
const a=12;
a=5; //报错,不能够修改
const b;
b=5; //报错,定义时就要给初始值
用途:为了防止意外修改变量,比如引入库名,组件名等

---------------------------------------------------------------------------------

3.字符串连接
之前都是用+进行字符串连接:
'abc'+变量名+'ef'

var a='我们';
var b='朋友';
var str='大家在一起'+a+'都是好'+b;

定义字符串的另外一种方法,使用反单引号
var str=`` (又称为字符串模板)
现在结合反单引号定义字符串,使用 ${变量名}进行连接 :
`abc${变量名}ef`

var a='我们';
var b='朋友';
var str=`大家在一起${a}都是好${b}`;

----------------------------------------------------------------------------

4.解构赋值:
var [a,b,c]=[12,2,43];

与json配合使用:与顺序无关,前后名称要相同
var{a,b,c}={a:12,b:5,c:16};
var{a,b,c}={b:5,a:12,c:16};
console.log(a);

模式匹配:左右的模式要相同
var [a,[c,d],b]=[12,[1,5],75];
var [{a,e},[c,d],b]=[{e:'eee',a:'aaa'},[1,5],75];

var arr=[{href:'abc',img:'12',src:'vnf'}];
var [{href,img,src}]=arr;
console.log(href);

之前json做判断给默认值:
var json={};
var a=json.a||12;
结构赋值给默认值:
var {time=12,id=6}={};
console.log(time,id);

放到返回值里面:
function getPos(){
return {stop:12,left:14};
}
var {stop,left}=getPos;
console.log(stop,left);

------------------------------------------------------------------------
4.复制数组:
方法1:循环
var arr1=[1,2,3];
var arr2=[];
for(var i=0;i<arr1.length;i++){
arr2.push(arr[i]);
}

方法2:Array.from(arr)
var arr1=[1,2,3];
var arr2=Array.from(arr1);

方法3:ES6新增——var arr2=[...arr];
var arr1=[1,2,3];
var arr2=[...arr1]; //复制arr1

[...]也可以与函数的传参结合在一起
通常我们定义一个函数,参数用arguments来表示,arguments是一个数组,但又不完全具备数组的性质
function show(arguments){
console.log(arguments);
//arguments.push(5); //这个是错误的,因为参数是由传进来的实参决定的
}
show(1,2,3,4);

我们可以通过...来方便的将arguments转变成一个真正的数组
function show(...args){
console.log(args);
args.push(5);
console.log(args); //1,2,3,4,5
}
show(1,2,3,4);

原文地址:https://www.cnblogs.com/yufann/p/ES6-note2.html