ES6 中新增特性
新增块级作用域
通过let 定义块级作用域
- 没有变量提升,变量必须先声明后使用
- 通过let 声明的变量不能重名
1
2
3
4
5
6
7// console.log(a) //报错 必须先定义后使用
let a = 0 //在全局中定义可以在全局中使用
function fun1(){
// let a = 1 // 报错不能重复定义相同的变量名
let b = 1 //只能在当前块,当前大括号中使用
}
通过const声明
- const声明变量的同时必须初始化,一旦初始化后这个变量的值就不允许修改
- const声明变量也是一个块级作用域的变量,只能在当前块使用
- const声明的变量也没有变量提升,必须先声明后使用
- const 声明的变量不能重名
1
2const a = 1
a = 2 //报错,a不允许修改
新增函数特性
函数可以设置默认参数
在我们调用函数时,如果设置了默认形参,如果没有给函数传参,那么函数可以使用默认形参
1 | function fun2(a=1,b=2){ |
同样,在构造函数中也可以使用此方法
1 | function Person(name,sex,age=10){ |
箭头函数
1 | // es5中的函数 |
使用箭头函数,我们可以使用多种方式书写函数,并且更简洁,更方便
但值得注意的是,在箭头函数中,没有this,换句话说,箭头函数中的this是外部作用域中的this
this指向问题
关于this指向问题相关 参考 《this指向问题》
展开运算符
将一个个数据打开成为一个个的状态,通过用它来展开数组或对象,也可以在函数传递参数的时候使用
1 | let arr= [1,2,3,4,5] |
解构赋值
快速从对象或者数组中获取成功
1 | //数组中的解构赋值 |
新增字符串方法
string.includes()
判断字符串是否包含一个指定的值,返回一个布尔值,表示是否找到了参数字符串。
1 | let s = 'abcdefg' |
还支持第二个参数,从哪个位置开始查找
1
2
3let s = 'abcdefg'
console.log('s.includes(d): ', s.includes("d",4)); //false
console.log('s.includes(d): ', s.includes("g",4)); //true
string.startsWith()
表示参数字符串是否在原字符串的头部,返回一个布尔值
1 | let s = 'abcdefg' |
同样也支持第二个参数,表示从哪个位置开始
1 | let s = 'abcdefg' |
string.endsWith()
返回布尔值,表示参数字符串是否在原字符串的尾部
1 | let s = 'abcdefg' |
也支持第二个参数,这个第二参数表示,从第0个到第n个
1 | let s = 'abcdefg' |
还有许多,详看 阮一峰的es6教程
Map 和 Set
- Map 和 Set 是 ES6 新增的两个数据类型
- 都是属于内置构造函数
- 使用 new 的方式来实例化使用
Set
Set 是一个构造函数,用来生成 Set 数据结构,它类似于数组,但是成员的值都是唯一的 , 没有重复的,初始化 Set 可以接受一个数组或类数组对象作为参数,也可以创建一个空的 Set:
1
2
3
4
5
6
7
8
9
10const s = new Set()
console.log('s', s)
//输出
/*
Set(0) {}
size: (...)
__proto__: Set
[[Entries]]: Array(0)
length: 0
*/我们可以在 new 的时候直接向内部添加数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// 实例化的时候直接添加数据,要以数组的形式添加
const s = new Set([1,2,3,{},function(){},true,'hello'])
console.log('s', s)
/*
Set(7) {1, 2, 3, {…}, ƒ, …}
size: (...)
__proto__: Set
[[Entries]]: Array(7)
0: 1
1: 2
2: 3
3: Object
4: function () {}
5: true
6: "hwllo"
length: 7
*/看上去是一个类似数组的数据结构,但不是数组,是Set 数据结构
常用的方法和属性
size
: 用来获取该数据结构中有多少数据的1
2const s = new Set([1,2,3,{},function(){},true,'hello'])
console.log('s', s.size) //7- 看上去是一个和数组数据类型差不多的数据结构,而且也看到的 length 属性
- 但是不能使用,想要获取该数据类型中的成员数量,需要使用 size 属性
add
: 用来向该数据类型中追加数据1
2
3
4
5
6
7
8// 初始化数据
const s = new Set([1,2,3,{},function(){},true,'hello'])
console.log('s', s.size) // 7
// 添加
s.add(0)
s.add({name:'guestljz'})
s.add({function (){ console.log("有点饿了")}})
console.log('s', s.size) //10- 这个方法就是向该数据类型中追加数据使用的
delete
: 用来删除该数据结构中的某一个数据1
2
3
4
5
6
7// 初始化数据
const s = new Set([1,2,3,{},function(){},true,'hello'])
console.log('s', s.size) // 7
// 删除
s.delete({})
console.log('s', s.size) // 9clear
: 清空数据结构中的所有数据1
2
3
4
5
6
7// 初始化数据
const s = new Set([1,2,3,{},function(){},true,'hello'])
console.log('s', s.size) // 7
//清空
s.clear()
console.log('s', s.size) // 0has
: 查询数据结构中有没有某一个数据1
2
3
4
5
6
7
8// 初始化数据
const s = new Set([1,2,3,{},function(){},true,'hello'])
console.log('s', s.size) // 7
// 查询
console.log(s.has(0)) // false
console.log(s.has({})) // true
forEach
: 用来遍历 Set 数据结构的方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// 初始化数据
const s = new Set([1,2,3,{},function(){},true,'hello'])
console.log('s', s.size) // 7
//遍历数据结构的每一项
s.forEach(ietm=>{
console.log('ietm: ', ietm);
//输出
/*
ietm: 1
ietm: 2
ietm: 3
ietm: {}
ietm: ƒ (){}
ietm: true
ietm: hello
*/
})方法介绍差不多了,但是有一个问题出现了,那就是
我们的方法添加 / 删除 / 查询 ,没有获取
获取 Set 结构里面的数据需要借助一个
...
展开运算符把他里面的东西都放到一个数组里面去,然后再去获取
1
2
3
4
5const s1 = new Set([1,2,3,4])
const a = [...s1]
console.log('a: ', a)
// 输出 a: (4) [1, 2, 3, 4]
console.log('a',a[0]) //1又有一个问题出现了,new的时候需要以数组的形式传递
然后获取的时候又要转成数组的形式获取
那为什么不一开始就定义数组,为什么要弄一个 Set 数据类型?
这不得不提到一个 Set 的特点
Set 不允许存储重复的数据
1
2
3
4
5const s = new Set([1,2,3])
s.add(4) //此时 size 是4
s.add(1) //此时 size 是4
s.add(2) //此时 size 是4
s.add(3) //此时 size 是4
Map
Map 是一个构造函数,用来生成 Map 数据结构,它类似于对象,也是键值对的集合,但是”键”可以是非字符串,初始化 Map 需要一个二维数组,或者直接初始化一个空的 Map:
1
2
3
4
5
6
7
8
9
10const m = new Map()
console.log(m)
/*
Map(0) {}
size: (...)
__proto__: Map
[[Entries]]: Array(0)
length: 0
*/在对象中不管存储什么, key 一定是一个字符串类型,对象是一个键值对 的集合 key : value
但是在 Map 里面,key 可以任意数据类型
Map 也可以叫做 (值 = 值) 的数据类型
1
2
3
4
5
6
7
8const m = new Map()
// 初始化的时候就给一些值
// 传递的参数需要是一个数组
// 数组需要是一个 二维数组
// 二维数组里面的每一个小数组接受两个数据
// 这个两个数据可以是任意数据类型
// 这个两个数据第一个就是 key,第二个就是 value
const m1 = new Map([['name', 'Jack'], [{ a: 100 }, 18]])
常用方法和属性
size
: t用来获取该数据类型中数据的个数1
2const m = new Map([[{}, {}], [function () {}, function () {}], [true, 1]])
console.log(m.size) // 3delete
: 用来删除该数据集合中的某一个数据1
2
3
4const m = new Map([[{}, {}], [function () {}, function () {}], [true, 1]])
m.delete(true)
console.log(m.size) // 2set
: 用来向该数据集合中添加数据使用1
2
3const m = new Map()
m.set({ name: 'Jack' }, { age: 18 })
console.log(m.size) // 1get
: 用来获取该数据集合中的某一个数据1
2
3
4
5const m = new Map()
m.set({ name: 'Jack' }, { age: 18 })
m.set(true, function () {})
console.log(m.get(true)) // function () {}clear
: 清除数据集合中的所有数据1
2
3
4
5
6
7
8const m = new Map()
m.set({ name: 'Jack' }, { age: 18 })
m.set(true, function () {})
m.clear()
console.log(m.size) // 0has
: 用来判断数据集合中是否存在某一个数据1
2
3
4
5
6const m = new Map()
m.set({ name: 'Jack' }, { age: 18 })
m.set(true, function () {})
console.log(m.has(true)) // trueforEach :遍历 MAP 数据集合中的成员
1
2
3
4
5const m = new Map()
m.set({ name: 'Jack' }, { age: 18 })
m.forEach(function (item) {
console.log(item)
})
模板字符串
ES5 中我们表示字符串的时候使用
''
或者""
在 ES6 中,我们还有一个东西可以表示字符串,就是 **``**(反引号)
区别是使用 **``**(反引号)我们可以在字符串里面使用
${变量名}
拼接变量使用 单引号再字符串中不能直接换行,使用反引号可以直接换行
Symbol类型
ES5 的对象属性名都是字符串,这容易造成属性名的冲突。
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。
在创建symbol类型数据时的参数只是作为标识使用,直接使用 Symbol() 也是可以的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41let s = Symbol('xm');
console.log( s );
console.log( typeof s );
//对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。
var xm = Symbol();
var obj = {
[xm] : "小明" //对象的属性是Symbol类型
}
//Symbol类型的属性 取值是 必须 obj[xm] 不能用obj.xm
console.log( obj[xm] );
var s4 = Symbol();
var obj = {
'name': 'xm',
[s4]: 'xh',
[Symbol('age')]: 18
}
console.log(obj); // {name: "xm", Symbol(): "xh", Symbol(age): 18}
console.log(obj.name); // xm
console.log(obj[s4]); // xh 访问对象的Symbol属性的值
console.log(obj[Symbol('age')]); // undefined
//修改symbol类型的属性
obj[xm] = "web前端";
console.log( obj[xm] );
//对象的Symbol属性不会被遍历出来(可以用来保护对象的某个属性)
var obj = {
"sname":"小明",
"skill" : "web"
}
var age = Symbol();
obj[age] = 18;
console.log( obj );
for( var key in obj ){
console.log(key + " -> " + obj[key] );
}Object.getOwnPropertySymbols 方法会返回当前对象的所有 Symbol 属性,返回数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25let id = Symbol("id");
let obj = {
[id]: '007',
[Symbol('name')]: 'xiaocuo'
};
let arr = Object.getOwnPropertySymbols(obj);
console.log(arr); //[Symbol(id),Symbol(name)]
console.log(obj[arr[0]]); //'007' 访问对象的Symbol属性的值
// 虽然这样保证了Symbol的唯一性,但我们不排除希望能够多次使用同一个symbol值的情况。
let s1 = Symbol('name');
let s2 = Symbol('name');
console.log( s1 === s2 ); // false
// 官方提供了全局注册并登记的方法:
let name1 = Symbol.for('name'); //检测到未创建后新建
let name2 = Symbol.for('name'); //检测到已创建后返回
console.log(name1 === name2); // true
// 通过symbol对象获取到参数值:
let name1 = Symbol.for('张三');
let name2 = Symbol.for('丽丽');
console.log(Symbol.keyFor(name1)); // '张三'
console.log(Symbol.keyFor(name2)); // '丽丽'