简介
es6 :ECMAScript6 第六个版本
ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发版。
注意:IE7~11 基本不支持 ES6 ,Chrome 和 Firefox 浏览器对 ES6 新特性最友好
与JavaScript的关系
ECMA是规定浏览器脚本语言的标准,JavaScript是脚本语言
ES6新增特性
新增 JavaScript 关键字: let 和 const
let 关键字
let 官方介绍
let 语句声明一个块级作用域的本地变量,并且可选的将其初始化为一个值。
块级作用域:在 ES6 之前,是没有块级作用域的概念的。
ES6 可以使用 let 关键字来实现块级作用域。
let 声明的变量只在 let 命令所在的代码块 {} 内有效,在 {} 之外不能访问。
{ let i = 1; } //等同于 (function (){ var i = 1 })()
个人总结
1.在同一个作用域中不能重复声明
2.没有声明提前
3.不挂载window
怕自己不信,举几个栗子
例子:
//不同作用域下,声明相同,此时,代码之间一片祥和
<script> let i = 0 console.log(i) //0 { let i = 1 console.log(i) //1 } </script>
同一作用域下再看看
let i = 0; let i = 2; // Uncaught SyntaxError: Identifier 'i' has already been declared console.log(i) { let i = 0; let i = 1; console.log(i) }
报错了,赶紧百度翻译一波
所以,在同一个作用域中不能重复声明
栗子2:
console.log(i) // i is not defined i未定义 let i = 0; console.log(i) //JavaScript逐行执行的特点,上面报错了,下面就不会执行咯
说明,没有声明提前
栗子3:
var a = 0 let i = 1;
console.log(window.i) //undefind console.log(window.a) //0
let作为ES6新增的语法 ,嚣张到就连window也管不了它
如何优雅的驾驭let语法
在ES6 的let出来之前,我们是这样解决问题的
输出的 i 始终是5,用this,可以获取点击的当前节点
var lis = document.getElementsByTagName('li') for (var i = 0; i < lis.length; i++) { lis[i].onclick = function (){ console.log(i) //点击任意li标签 打印始终为5 console.log(this) //点击任意li标签 打印对应的节点 } }
有了立即执行函数后:
var lis = document.getElementsByTagName('li') for (var i = 0; i < lis.length; i++) { (function(i){ lis[i].onclick = function (){ console.log(i) //0,1,2,3,4 } })(i) }
有了let后,画风就不一样了
var lis = document.getElementsByTagName('li') for (let i = 0; i < lis.length; i++) { lis[i].onclick = function (){ console.log(i) //0,1,2,3,4 } }
据说,let比var更利于性能优化
尝试一波:
用var声明测试效率
console.time('test')
for (var i = 0; i < 100000; i++) {
var obj = {"abc":"456"}
var num = 1000+i;
var str = "鸡你太美";
var obj2 = {"abc":"456"}
var num2 = 1000+i;
var str2 = "鸡你太美";
}
console.timeEnd('test') //test: 14.98193359375ms
用let声明测试效率
console.time('test')
for (var i = 0; i < 100000; i++) {
let obj = {"abc":"456"}
let num = 1000+i;
let str = "鸡你太美";
let obj2 = {"abc":"456"}
let num2 = 1000+i;
let str2 = "鸡你太美";
}
console.timeEnd('test') //test: 4.18994140625ms
关于let 临时死区(面试常考)
let i = 1; console.log(i); //1 { console.log(i); //1 }
块级作用域是可以访问到父级作用域
let num = 200; { console.log(num);//Uncaught ReferenceError: num is not defined 未捕获引用错误:未定义num, 被称为临时死区 let num = 300; }
块级作用域内声明与父级作用域相同的变量名,则会报错未捕获引用错误:未定义num,这被称为临时死区
面试题2
for(var i = 0;i < 10;i++){ setTimeout(function(){ console.log(i); },0) } console.log(i)
控制台输出什么?
第一个打印 10
第二个打印 10个10
如何改动代码让其输出0,1,2,3,4,5,6,7,8,9,10
只有将定时器去掉
1.将var 改为 let的话 输出为
0,1,2,3,4,5,6,7,8,9 ,{}外的i 会报错i is not defined
2.定时器套上立即执行函数 输出为
10,0,1,2,3,4,5,6,7,8,9
let思索
function test(a){ //参数到底是let声明还是var声明 let a = 100; console.log(a) //Uncaught SyntaxError: Identifier 'a' has already been declared 未捕获语法错误:标识符“a”已声明 } test()
const 关键字
与let之间的区别
const
声明的常量必须初始化,而let
声明的变量不用
const 定义常量的值不能通过再赋值修改,也不能再次声明。而 let 定义的变量值可以修改。
常量名,人为规定书写大写字母,便于区分数据类型
能用const用const 不能用再用let
与let相同点
1.在同一个作用域中不能重复声明
2.没有声明提前
3.不挂载window
ES6/7...展开&收集运算符:(超引用)
常出没node中
可以这么用:
function fun(...arr){
console.log(arr) //[1,2,3,4] //形参以数组的方式传入 console.log(arguments) //Arguments(4) [1, 2, 3, 4, callee: (...), Symbol(Symbol.iterator): ƒ] } fun(1,2,3,4)
也可以这么用:
let arr =[1,2,3,4] function fun(...a){ console.log(a) //[1,2,3,4]
}
fun(...arr)
ES6可以这么用:
let arr = [1,2,3,4] let arr1 = [0,...arr,5,6] //[0,1,2,3,4,5,6]
看看是否相同:
let arr = [1,2,3,4]
let arr1 = [...arr]
console.log(arr === arr1) //false
//引用地址不同
ES7可以用在对象上
let obj = { age : 18, name : "jack", sex : "gril", a :1 } let obj1 = { age : 28, name : "tony", sex : "gril", ...obj }
console.log(obj1) //{age: 18, name: "jack", sex: "gril", a: 1}
利用 Object.assign()
方法浅克隆
Object.assign()
方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
Object.assign()第一个参数是目标对象,后面的都是源对象。
Object.assign(target, ...sources);
参数:
- target: 目标对象
- sources: 源对象
返回值:
*目标对象
let obj = { a : 1, b : 2, c : 3 } let obj2 = { d :4, e :5, g :{i:10} } let copy =Object.assign({},obj,obj2) //浅克隆,只是克隆了引用地址 copy.g.i = 1 console.log(copy.g.i) //1 console.log(obj2.g.i) //1
利用...来浅克隆
let obj = { a : 1, b : 2, c : 3 } let obj2 = { d :4, e :5, g :{i:10} } let obj3 = { ...obj, ...obj2 //浅克隆 } obj3.g.i = 1 console.log(obj3.g.i) //1 console.log(obj2.g.i) //1
利用...来深克隆
let obj = { a : 1, b : 2, c : 3 } let obj2 = { d :4, e :5, g :{i:10} } let obj3 = { ...obj, ...obj2, g : { ...obj2.g } } obj3.g.i = 1 console.log(obj3.g.i) //1 console.log(obj2.g.i) //10
解构(结构化赋值)
将等于号两边结构相同的声明与变量进行赋值
数组
例子:
let [a,b,c] = [1,2,3] console.log(a,b,c) //1 2 3
对象
例子:
let obj = { a :1, b :2 } let {a ,b }= obj console.log(a,b) //1 2 let obj2 = { c :3, d :4 } let c,d; ({c,d} = obj2) console.log(c,d) //3,4
在函数中的应用
例子
function add(a = 1,b = 2){ return a + b; } console.log(add()) //3 console.log(add(10,20)) //30
箭头函数
写法;
例子
//基本玩法
var fun = () =>{ console.log(1) //1 } fun()
//带参玩法
let sum = (a,b) => a+b;
console.log(sum(10,20)) //30
//花式嵌套玩法
let sum = x => y => z => x+y+z;
console.log(sum(1)(2)(3)) //6
注意:
不绑定this
,this指向window
不绑定arguments
不能使用 new
操作符
箭头函数没有prototype
属性