90% 前端都会的 ES6 简化代码技巧,你用过哪些?
- 块级作用域
- 解构
- 箭头函数
- 模板字符串
- 剩余参数 / 展开语法
- 对象字面量简写语法
- 数组实例的 includes()
- Async / await 异步语法
块级作用域
为什么需要块级作用域?
ES5只有全局作用域和函数作用域,没有块级作用域,这导致很多场景不合理。
- 第一种场景,内层变量可能会覆盖外层变量。
以上代码的原意是,if代码块外部使用外层的 tmp 变量,内部使用内部的 tmp 变量。但是,函数 fn 执行后,输出的结果为 undefined,原因在于变量提升导致内层的 tmp 变量覆盖了外层的 tmp 变量。
- 第二种场景,用来计数的循环变量泄露为全局变量。
上面代码中,变量 i 只是用来控制循环,但是循环结束后,他并没有消失,而是泄露成了全局变量。
let 实际上为 JavaScript 新增了块级作用域。
上面的函数有两个代码块,都声明了变量 n ,运行后输出 5 。这表示外层代码块不受内层代码块的影响。如果使用 var 定义变量,最后输出的值就是 10。
结构
解构:是将一个数据结构分解为更小的部分的过程。ES6中,从数组和对象中提取值,对变量进行赋值。
// ES5
var foo = 1
var bar = 2
var baz = 3
// ES6
let [foo,bar,baz] = [1,2,3]
let x = 1
let y = 2
[x,y] = [y,x]
// x = 2, y = 1
var obj = { x:1,y:2,c:1 }
let { x,y } = obj
// x = 1
// y = 2
const [a,b,c,d,e] = hello
// a => h
// b => e
// c => l
// d => l
// e => o
const shaochang = {name:'少昌',age:18}
function getAge({ name,age }){ return `${name}今年${age}岁` }
getAge(shaochang) // 少昌今年18岁
箭头函数
var f = v => v
// 等同于ES5的
var f = function(v){ return v }
var f = () => 5
// 等同于 ES5 的
var f = function (){ return 5 }
var sum = (num1,num2) => num1 + num2
// 等同于 ES5 的
var sum = function(num1, num2){ return num1 +num2 }
const full = ({ first, last }) => first + + last;
// 等同于 ES5 的
function full(person){
return person.first + + person.last;
}
const isEven = n => n % 2 === 0
const square = n => n * n
var result = values.sort((a, b) => a - b)
// 等同于 ES5 的
var result = values.sort(function (a, b) { return a - b })
箭头函数使用注意点。
1.函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。
2.不可以当做构造函数,也就是不可以使用 new 命令,否则会抛出一个错误。
3.不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以使用 rest 参数代替。
4.不可以使用 yield 命令,因此箭头函数不能作 Generator 函数。
// ES6
function foo() { setTimeout(() => { console.log(id:,this.id) },100) }
// 转换成 ES5
function foo(){ var _this = this; setTimeout(function () { console.log( id:,_this.id ) },100) }
上面代码中,转换后的 ES5 版本清楚地说明了,箭头函数里面根本没有自己的 this,而是引用外层的 this。
模板字符串
const { log } = console
const name = wenshaochang
const age = 18
// 普通字符串拼接
const result = name + '今年' + age + '岁'
// 使用模板字符串
const result2 = `${name}今年${age}岁`
log(result) // wenshaochang今年18岁
log(result2) // wenshaochang今年18岁
// ${} 大括号可以放入任意的 JavaScript 表达式,可以进行运算
const result3 = `${name}今年${age * 2}岁`
log(result3) // wenshaochang今年36岁
剩余参数 / 展开语法
function sortNumbers(){ return Array.prototype.slice.call(arguments).sort() }
// 使用 rest
const sortNumbers = (...numbers) => numbers.sort()
console.log(...[1, 2, 3]) // 1 2 3
console.log(1,...[2,3,4],5) // 1 2 3 4 5
// ES5 的写法
Math.max.apply(null,[14,2,77])
// ES6 的写法
Math.max(...[14,3,77])
// 等同于
Math.max(14,3,77)
// ES5
[1,2].concat(more)
// ES6
[1,2,...more]
let z = { a:3, b:bb }
let n = { ...z }
n // { a:3, b:bb }
n === z // false
let z = { a: 3, b: bb , c: { name: ccc } }
let n = { ...z }
n // { a: 3, b: bb , c: { name: ccc } }
n === z // false
n.c === z.c // true
// n.c 跟 z.c 是同一个引用地址
对象字面量简写语法
const name = wen
// ES5 写法
const obj = {
name:name,
f:function(){
console.log(this.name)
},
}
// ES6 简写
const obj2 = {
name,
f(){
console.log(this.name)
}
}
obj.f() // wen
obj2.f() // wen
数组实例的 includes()
[1,2,3].includes(2) // true
[1,2,3].includes(4) // false
[1,2,NaN].includes(NaN) // true
// ES5
if (arr.indexOf(el) !== -1) {
// ...
}
// ES6
if (arr.includes(el)) {
// ...
}
// 那么 indexOf 能不能做到类似于 includes 的写法呢? 我们可以利用 ~ 位运算符
if (~arr.indexOf(el)) {
// ...
}
;[NaN].indexOf(NaN) // -1
;[NaN].includes(NaN) // true
Async / await 异步语法
async function getTitle(url) {
let response = await fetch(url)
let html = await response.text()
return html.match(/([sS]+)/i)[1]
}
getTitle( https://tc39.github.io/ecma262/ ).then((res) => console.log(res))