es6常用特性
1. let和const命令
- let声明的变量会产生块级作用域
var a = 2
{
let b = 1
console.log(b) // 1
}
console.log(a) // 2
console.log(b) // b is not defined
- let 不可以重复声明一个变量(同一作用域)
{
let b = 1
let b = 2
console.log(b) // error Parsing error: Identifier 'b' has already been declared
}
- let不存在变量提升
var 命令会发生“变量提升”现象,即变量可以在声明之前使用,值为 undefined。 let 命令改变了语法行为,它所声明的变量一定要在声明后使用,否则会报错
console.log(a); //undefined
var a= 2;
console.log(b); // ReferenceError: bar is not defined
let b= 2;
- const是声明常量的,一旦声明值就不可改变,且声明的时候必须初始化
const a
a = 1
console.log(a) // error Parsing error: Const declarations require an initialization value
const a = 1
a = 2
console.log(a) // error 'a' is constant
2. 箭头函数
基本用法(对于带有一个参数只执行一条语句的函数,()和{} 可以省略)
无参数:() => {}
单个参数:x => {}
多个参数:(x, y) => {}
箭头函数的this指向问题
- ES6箭头函数里this的指向就是上下文里对象this指向,偶尔没有上下文对象,this就指向window
- call,apply,bind等方法也不能改变箭头函数this的指向
demo:
aa是全局函数,没有直接调用它的对象,也没有使用严格模式,this指向window
function aa() {
console.log(this); // window
}
aa();
hello是全局函数,没有直接调用它的对象,但指定了严格模式(‘use strict’),this指向undefined
function aa() {
'use strict';
console.log(this); //undefined
}
aa();
aa直接调用者是obj,第一个this指向obj,setTimeout里匿名函数没有直接调用者,this指向window
const obj = {
num: 10,
aa: function () {
console.log(this); // obj
setTimeout(function () {
console.log(this); // window
});
}
}
obj.aa();
aa直接调用者是obj,第一个this指向obj,setTimeout箭头函数,this指向最近的函数的this指向,即也是obj
const obj = {
num: 10,
aa: function () {
console.log(this); // obj
setTimeout( () => {
console.log(this); // obj
});
}
}
obj.aa();
aa是普通函数,里面的this指向直接调用它的对象obj。bb是箭头函数,this应该指向上下文函数this的指向,这里上下文没有函数对象,就默认为window,而window里面没有num这个变量,所以返回NaN
const obj = {
num: 10,
aa() {
return this.num * 2
},
bb: () => 2 * this.num
}
console.log(obj.aa()) // 20
console.log(obj.bb()) // NaN
3. 对象的新增方法Object.assign()
- 对象的合并
Object.assign()方法的第一个参数是目标对象,后面的参数都是源对象
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
console.log(target); //{a: 1, b: 2, c: 3}
注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性
const target = { a: 1 , b: 1};
const source1 = { b: 2 , c:2};
const source2 = { c: 3 };
Object.assign(target, source1, source2);
console.log(target); //{a: 1, b: 2, c: 3}
如果只有一个参数,Object.assign()会直接返回该参数
const target = { a: 1 , b: 1};
const source1 = { b: 2 , c:2};
const source2 = { c: 3 };
Object.assign(target);
console.log(target); //{a: 1, b: 1}
- 给对象添加属性
const arr = [{
name: 'tom',
age: 13
},
{
name: 'jerry',
age: 13
}
]
let newArr = arr.map((item, index) => Object.assign(item, {id: index + 1}))
console.log(newArr)
运行结果
- 对象的拷贝
深拷贝:
let obj = {
name: 'tom',
age: '20'
};
let cloneObj = Object.assign({}, obj, {
age: '21'
});
cloneObj.name = 'jerry';
cloneObj.age = '23';
console.log(obj); //{name: "tom", age: "20"}
console.log(cloneObj); //{name: "jerry", age: "23"}
浅拷贝:
const obj = {
name: 'tom',
tom: {
age: 12
}
}
const cloneObj = Object.assign({}, obj)
cloneObj.name = 'jerry'
cloneObj.tom.age = 18
console.log(obj) //{name: 'tom',tom:{age:18}}
console.log(cloneObj); //{name: 'jerry',tom:{age:18}}
总结:
从例子中可以看出,改变复制对象的name 和 tom.age,源对象的name没有变化,但是tom.age却被改变了。因此可以看出Object.assign()拷贝的只是属性值,假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。
也就是说,对于Object.assign()而言, 如果对象的属性值为简单类型(string, number),通过Object.assign({},obj);得到的新对象为‘深拷贝’;如果属性值为对象或其它引用类型,那对于这个对象而言其实是浅拷贝的。这是Object.assign()需要注意的地方
4. new Set()的基础用法
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成 Set 数据结构
- 增删改查
(1)添加元素add:
添加某个值,返回 Set 结构本身
let list = new Set()
list.add(1)
list.add(2).add(3).add(4)
console.log(list);// Set(4){1, 2, 3, 4}
(2)删除元素delete:
删除某个值,返回布尔值,表示删除是否成功
let list = new Set([1,2,3,4,5])
console.log(list.delete(1)); //true
console.log(list); //Set(4){2, 3, 4, 5}
(3)判断是否存在某元素has:
返回一个布尔值,判断该值是否为Set的成员
let list = new Set([1,2,3,4,5])
list.has(1); //true
(4)清除所有元素clear:
清除所有成员,没有返回值
let list = new Set([1,2,3,4,5])
list.clear();
console.log(list); //Set(0){}
- 使用情形
(1)数组去重
let arr = [1,2,3,4,3,5,2]
let newArr = [...new Set(arr)] // [1, 2, 3, 4, 5]
(2)字符串去重
let string = '2341212'
let newString = [...new Set(string)].join("") // "2341"