推荐ES6相关链接:
1、var/let/const
(1)var/let
用来声明变量,var
只有全局作用域和函数作用域的概念,没有块级作用域的概念;let
只有会计作用于的概念由{ }
包起来,if语句和for语句里面的{ }
也属于块级作用域。
众所周知,
var
声明变量,存在变量提升,那么let
究竟是否存在变量提升呢?
实际上let
声明的变量是存在变量提升的,但是由于【暂时性死区(temporal dead zone),简称TDZ】我们无法在声明前访问这个变量。
- 暂时性死区:如果区块中存在
let
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错,所以在代码块内,使用let
命令声明变量之前,该变量都是不可用的。 - 换言之,只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。即:
let
定义的变量会被提升,但是不会被初始化,不能被引用,const
也一样,而var
在定义的时候,初始值被赋予了undefined
。
(2)const
建议用来声明简单类型的数据,更多用来声明常量,const
一旦被赋值,就不能再改变了,但是这并不意味着const
声明的变量本身不可变,只是说它不可以被再次赋值了,而且const
声明的变量必须经过初始化。
参考链接:总结下var、let和const 的区别
2、箭头函数
基础语法:
- 将原函数的
function
关键字和函数名都删掉,并使用=>
连接参数列表和函数体;
var fn1 = function(a, b) {
return a + b
}
var fn1 = (a, b) => {
return a + b
}
- 当函数参数只有一个,括号可以省略,但是没有参数的时候,括号不可以省略。
// 无参
var fn1 = function() {}
var fn1 = () => {}
// 单个参数
var fn2 = function(a) {}
var fn2 = a => {}
// 多个参数
var fn3 = function(a, b) {}
var fn3 = (a, b) => {}
// 可变参数
var fn4 = function(a, b, ...args) {}
var fn4 = (a, b, ...args) => {}
- 返回一个对象时,如果是单表达式要返回自定义对象,不写括号会报错,因为和函数体的
{…}
有冲突。
x => {key: x} // 报错
x => ({key: x}) // 正确
this指向:
箭头函数看上去是匿名函数的一种简写,但实际上,箭头函数和匿名函数有个明显的区别:箭头函数内部的this是词法作用域,由上下文确定。(词法作用域就是定义在词法阶段的作用域。换句话说,词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的,因此当词法分析器处理代码时会保持作用域不变 。)
总结:
(1)普通函数的this
指向调用它的那个对象,箭头函数this为父作用域的this
,不是调用时的this
,任何方法都改不了,包括call
、apply
、bind
。
(2)箭头函数不能作为构造函数,不能使用new
。
(3)箭头函数没有argument
、caller
、callee
。
(4)箭头函数通过call
和apply
调用,不会改变this
指向,只会传入参数。
(5)箭头函数没有原型属性。
(6)箭头函数不能作为Generator
函数,不能使用yield
关键字。
(7)箭头函数返回对象时,要加一个小括号。
(8)箭头函数在ES6 class
中声明的方法为实例方法,不是原型方法。
参考链接:
1》ES6新特性箭头函数语法,如何正常使用箭头函数
2》箭头函数详解
3、解构赋值:通过一种特定的格式,快捷的读取对象或数组中的数据方法。
- 交换变量:常见的两个变量交换的方法都是需要借助一个额外的变量,解构运算使得交换变量的值变得简单。
//常见方法
let a = 1;
let b = 2;
let temp;
temp = a;
a = b;
b = temp;
a; // => 2
b; // => 1
//解构运算
let a = 1;
let b = 2;
[a, b] = [b, a];
a; // => 2
b; // => 1
[a, b] = [b, a]
是一个解构运算。在等号的右侧,创建了一个数组[b, a],对应的值为[2, 1]。数组的第一个值2被解构赋值给了a,第二项1被解构赋值给了b。
这种方式没有什么限制,可以同时交换更多的变量值。
- 解构数组:数组用
[]
解构
let arr = [10, 11, 12, 13];
let [one, tow] = arr;
console.log(one, tow);// 10 11
//对不需要解构的值,可以用逗号占位
let [, , , four] = arr;
console.log(four);//13
- 解构对象:
解构出来的变量 一定要是对象中能够查找到的属性名
var User = {
'name' : 'ghostwu',
'age' : 22
};
let { name1, age1 } = User;
console.log( name1, age1 ); //undefined, undefined
let { name, age } = User;
console.log( name, age ); //ghostwu 22
更改解构出来的变量名称的语法: 旧的名称 : 新的名称
//解构出来的变量可以更改名称
let { name : name1, age : age1 } = User;
// console.log( name, age ); //报错, 因为name和age的名称已经被改了
console.log( name1, age1 ); //ghost, 22
可以给不存在的属性赋初始值,但是已存在的值,不可以改变
// 解构出来的值 可以赋值 一个默认的值
let { name, age = 18, sex = 'man' } = User;
console.log( name, age, sex ); //ghost, 22, man
4、for in / for of
for in
循环出的是key
,for of
循环出的是value
。- 对普通对象的遍历推荐使用
for in
,for of
循环不会循环对象的key
,只会循环出数组的value
,因此for of
不能循环遍历普通对象。 - 在遍历数组的时候使用
for of
,因为for in
在遍历数组时,除了会遍历数组元素以外,还会遍历自定义属性,而for of
不会。 for of
不能循环普通的对象,需要通过和Object.keys()
搭配使用。
var arr=[{name:'张三'},{name:'李四'}]; //数组
var obj={name:'张三', age: 11}; //对象
//for in遍历数组返回数组或对象的key
for (var i in arr){
console.log(i)
}
for (var i in obj){
console.log(i)
}
//0
//1
//name
//age
//for of遍历数组 返回value值
for (var i of arr){
console.log(i)
}
//{name: "张三"}
//{name: "李四"}
// for of不能循环对象,需配合Object.keys()使用,返回value值
for(var key of Object.keys(obj)){
console.log(obj[key])
}
//"张三"
//11
var student={
name:'zh',
age:22,
locate:{
country:'china',
city:'xiamen',
}
}
for(var key of Object.keys(student)){
//使用Object.keys()方法获取对象key的数组
console.log(key+": "+student[key]);
}
其他遍历方法了解链接:for in 和 for of 的区别