未来已来,突然好喜欢这句话,哈哈。
ES6 已经离我们越来越近了,不久前发布了 ES6 标准文档,而 babel 社区如火如荼,对于 ES6 究竟给 js 开发者们带来了什么东西,我们来简单地了解一下。
这个文章并不会深入讲解某一部分的内容,只是帮助你快速地浏览一下 ES6 相关的东西究竟有哪一些,毕竟,其中每一部分的内容深入探讨都足够是一篇新的文章。
let foo = {
x: 1,
y() {
return (x) => this.x + x + arguments[0]
}
}
let add = foo.y(1)
add(1) // 3
箭头声明的函数有以下特征:
- 词法 this 绑定
- this 无法使用 call 或者 apply 进行修改
- 词法 arguments 绑定
传入参数为 undefined 或者不传入参数时使用默认值,默认值可以引用前边的参数值
function foo(a = 1, b = 2, c = b, d = 4) {
return a === 1 && b === 3 && c === 3 && d === 4
}
foo(undefined, 3) // true
// 默认值为一个 function
function bar(a = (x) => { return x }) {
return a(1) === 1
}
bar() // true
使用 ...
来声明剩下参数部分为一个数组
function foo(a, ...b) {
return a === 1 && b[0] === 2 && b[1] === 3
}
foo.length // 1
foo(1, 2, 3) // true
可以使用 ... 来对数组或者字符串进行展开操作,使其变成 item1, item2 ..
的格式
let a = [1, 2, 3]
function foo(a, b, c) {
return a === 1 && b === 2 && c === 3
}
foo(...a) // true
[0, ...a, 4][1] === 1 // true
[0, ...'hello'][1] === 'h' // true
- 属性名可以是一个表达式
- 属性名可以直接沿用变量名
- 函数的简写
let x = 'y'
let a = {
[x]: 1,
x,
hello() {
return 1
},
'hello world'() {
return 2
},
[1 + x]() {
return 3
}
}
a.x === 'y' // true
a.y === 1 // true
a.hello() === 1 // true
a['hello world']() === 2 // true
a['1y']() === 3 // true
使用 for..of 对实现了迭代接口的对象进行循环
let arr = [1, 2, 3]
let str = 'hello'
for (let item of arr) {
console.log(item)
}
for(let char of str) {
console.log(char)
}
let a = 0o12
a === 10
let b = 0b10
b === 2
let c = Number('0b11')
c === 3
let a = 'hel', b = 'WORLD'
let temp = `${a + 'lo'}, ${b.toLowerCase()}`
console.log(temp) // hello, world
可以从一个现有数组来推导出一个新的数组
var a1 = [1, 2, 3, 4]
var a2 = [for (i of a1) i * 2] // [2, 4, 6, 8]
a2[1] === 4 // true
let [a, , [b], c] = [1, null, [2], 3]
a === 1 // true
b === 2 // true
c === 3 // true
let [a, b, c] = 'ab'
a === 'a' // true
b === 'b' // true
c === undefined // true
let {x, a: y, z} = {
x: 1,
a: 2
}
x === 1 // true
y === 2 // true
z === undefined // true
可以使用解构来获取一些对象的方法
let {toFixed} = 2
let {slice} = ''
toFixed === Number.prototype.toFixed // true
slice === String.prototype.slice // true
和多个语法糖结合起来后还有很多应用场景
// for-of
for (let [key, value] of [[1, 2], [2, 3]]) {
console.log(key, value)
}
// rest
let [a, ...b] = [1, 2, 3]
a === 1 // true
b[1] === 3 // true
// function params
function move({x = 1, y = 2} = {}) {
return [x, y]
}
move()
move({x: 3, y: 8}) // [3, 8]
let
和 const
- 定义块级作用域的变量
- 定义常量
const a = 1
a === 1 // true
{
let b = 2
b === 2
}
// b is not defined
对原有的扩展很多,这里只是讲了感觉可能比较有用的一部分
-
is
用于判断是否两个值是否相同
Object.is(0, -0) // false Object.is([], []) // false Object.is(window, window) // false
-
assign
用于扩展对象的属性,类似 jQuery.extend 方法
let o1 = { a: 1 }; let o2 = { b: 2 }; let o3 = { c: 3 }; let obj = Object.assign(o1, o2, o3); // { a: 1, b: 2, c: 3 } obj === o1 // true
-
from
用来从一个实现了迭代接口的对象来生成一个数组
let m = new Set() m.add(1) m.add(2) let arr = Array.from(m, (item) => item + 1) console.log(arr)
-
of
以传入的参数为元素返回一个数组,主要是为了弥补 Array 构造器的不足
-
find
用来从目标数组中找出符合条件的第一个元素,类似 lodash 中的
_.find(array, [identity], [thisArg])
let arr = [1, 2, 3, 4] arr.find((x) => x >= 2) == 2 // true
-
findIndex
类似 find 方法,差别就是这个是返回索引
let arr = [1, 2, 3, 4] arr.findIndex((x) => x >= 2) == 1 // true
-
fill
用于填充数组内容,类似 lodash 中的
_.fill(array, value, [start=0], [end=array.length])
let arr = Array(3) arr.fill(1) // [1, 1, 1] arr[2] === 1
-
entries
获取可以遍历数组的迭代器,常和 for...of 配合使用
let arr = [1, 2, 3] for (let [index, item] of arr.entries()) { console.log(index, item) }
-
repeat
重复字符串 n 次,类似 lodash 中的
_.repeat([string=''], [n=0])
'*'.repeat(3) // '***'
-
startsWith
判断字符串是否以某个字符串开头,类似 lodash 中的
_.startsWith([string=''], [target], [position=0])
'hello world'.startsWith('world', 6) // true
-
endsWith
判断字符串是否以某个字符串结束,类似 lodash 中的
_.endsWith([string=''], [target], [position=string.length])
-
includes
判断字符串是否包括某个字符串,类似 lodash 中的
_.includes(collection, target, [fromIndex=0])
'hello world'.includes('wor') // true
这一部分主要用于进行数组的类型判断,方法名一看就懂,这里不做详细阐述。
- isFinite
- isNaN
- isInteger
这个主要是提供了任意字节为基础的多种数据接口来更好地支持网络协议实现,加密算法,文件格式操作等,前端涉及的可能会少一点,这个不在这里做探讨(需要的话再另外深入了解下)。
两种方便操作的数据格式,Set 是元素不重复的集合,Map 是 key 不重复的集合,举两个简单的例子,这里也不做深入探讨:
Set 的简单使用:
let s = new Set()
let count = 0
s.add(1)
s.add(1)
s.add(2)
s.forEach((item) => {
count++
console.log(item)
})
count === 2 // true
s.has(1) // true
Map 的简单使用:
let m = new Map()
m.set('hello', 1)
m.set('world', 2)
m.get('hello') // 1
for (let [key, value] of m.entries()) {
console.log(key, value)
}
这个是极其强大的功能,可以创建代理对象,把相关对象的操作代理到自己设置的方法中,例如:
let tar = { foo: 'hello' }
let proxy = new Proxy(tar, {
get (receiver, name) {
return 'world'
}
})
proxy.foo // 'world'
proxy.bar // 'world'
这是运行时级别对于对象的元编程操作,不过现有的类似 babel,traceur 都是没法支持的,这个需要从浏览器基础上去支持,所以离真正能够用上还有一段时间。
这个已经在广泛使用了,被认为是一个很好的实践方式,ES6 才将其纳入实现标准中。这里不再阐述 Promise 相关内容,如果有需要,再起文章来说明好了。
一种新的原始数据类型,用于代表独一无二的 id,来防止对象属性或者方法名称的使用冲突。简单的使用:
let s = Symbol('symbol')
s === Symbol('symbol') // false
let obj = {
[s]: 'hello world'
}
obj[s] === 'hello world' // true
Symbol.for
的话会从全局搜索标识,有则返回,没有才生成一个新的,而不是每次都是产生一个新的,和 Symbol
不一样。
Symbol.�keyFor
可以获取一个 symbol 变量的 key 标识。
let s = Symbol.for('symbol')
s === Symbol.for('symbol') // true
'symbol' === Symbol.keyFor(s) // true
注意,symbol 变量是无法和其他类型的值进行运算的,会抛出错误。
ES6 相关的内容很多,接纳了 js 发展历程中社区的很多实践和贡献,吸收了很多语言的优秀特性,随着 js 应用场景的扩展也添加了很多适应的特性,主要都是为了让 js 更好地成为一个企业级别的开发语言。
虽然说现在 ES6 没法直接投入到浏览器端的生产环境中,但是已经有 babel 等方案让我们可以更早地使用 ES6 的特性来进行开发,所以让我们现在就开始拥抱 ES6,拥抱 js 的美好未来。