ES6常用语法和方法总结

小菜鸟战斗机 2018-3-26 180

ES6阮一峰老师的书已经出到第三版了,从中受益匪浅,第二版读了三遍,在项目中常用到的一些语法和方法做些总结

字符串扩展

常用的一些方法

at()

// 参数传入角标,返回值为角标对应的字符
'abc'.at(0) // 'a'
'吉'.at(0) // '吉'
// 与ES5中charAt()不同之处,汉字的话ES5会返回对应Unicode编码,js内部用UTF-16
includes(), startsWith(), endsWith()

includes(),返回值为布尔值,表示是否找到参数的字符串
startsWith(),返回值为布尔值,表示参数字符串是否在原字符串的头部
endsWith(),返回布尔值,表示参数字符串是否在原字符串的尾部
这三个方法都支持第二个参数,表示开始搜索的位置。endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。
let str = 'Hello World'
str.includes('Hello') // true
str.startsWith('Hello') // true
str.endsWith('d') // true
str.startsWith('world', 6) // true
str.endsWith('Hello', 5) // true
str.includes('Hello', 6) // false
repeat()

'x'.repeat(3) // "xxx"
注意:参数不能传负数和Infinity,参数NaN为0,参数为字符串会先转换为数字
padStart(),padEnd()

参数两个,第一个为位数,第二个是用什么补全,省略第二个参数时默认为空格补全。这两个更多的用途是补全指定位数
'1'.padStart(10, '0') // "0000000001"
'12'.padStart(10, '0') // "0000000012"
'123456'.padStart(10, '0') // "0000123456"
数组扩展

Array.from()

Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)
...运算符

扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
console.log(...[1, 2, 3])
// 1 2 3

console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
关于函数传参的问题,如果函数直接用...传参,传入的参数实际上是个数组,且后面不能再有参数。如果函数参数定义了一个数组,用...传入,实际上参数为数组中的值
function fn(...items){}
//等同于
function fn([数组内容]){}

let items = ['a', 'b', 'c']
function fn(...items){}
// 等同于
function fn('a', 'b', 'c') {}
...运算符的应用

复制数组(克隆数组)
let arr1 = [1, 2, 3]
let arr2 = [...arr1] // [1, 2, 3]
合并数组
const arr1 = ['a', 'b']
const arr2 = ['c']
const arr3 = ['d', 'e']
const arr4 = [...arr1, ...arr2, ...arr3] // [ 'a', 'b', 'c', 'd', 'e' ]
与解构赋值结合
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
将字符串转换为真正的数组
[...'hello']
// [ "h", "e", "l", "l", "o" ]
Array.of(), 用于将一组值,转换为数组。

Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
数组实例的fill()

三个参数,后面两个可以省略,第一个参数为替换成什么内容,第二个为替换的起始位置,第三个为替换的终止位置
['a', 'b', 'c'].fill(7)
// [7, 7, 7]

['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']
数组实例的 entries(),keys() 和 values()

三个方法都是遍历数组,都可以用for...of...唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。
for (let index of ['a', 'b'].keys()) {
console.log(index);
}
// 0
// 1

for (let elem of ['a', 'b'].values()) {
console.log(elem);
}
// 'a'
// 'b'

for (let [index, elem] of ['a', 'b'].entries()) {
console.log(index, elem);
}
// 0 "a"
// 1 "b"
对象扩展

对象的话,解构赋值就不说了太基础了,我用的最多的就是...运算符和Object.assgin(),好吧,实际上...底层的方法就是assign()

Symbol

js数据类型除了string,number,boolean,undefined,null,object,第七种为symbol,他的作用就是防止定义变量时出现重复的定义导致覆盖的一些问题,这个我知道有这个,但从没用过

Set和Map结构

Set

ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。Set 本身是一个构造函数,用来生成Set数据结构。此结构不会添加重复的值(你想到了什么,一定想到了数组去重)
// 例一
const set = new Set([1, 2, 3, 4, 4]);
[...set]
// [1, 2, 3, 4]

// 例二
const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
items.size // 5

// 例三 数组去重
[...new Set(array)]
Map

这个结构我个人感觉不如对象好用,没用过。实际上Map结构就是键值对的结构,里面设置和获取分别用set和get方法,我要设置的话每次都set一下,我觉得很不方便
Proxy拦截

基本说明

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
var obj = new Proxy({}, {
get: function (target, key, receiver) {
console.log(getting ${key}!);
return Reflect.get(target, key, receiver);
},
set: function (target, key, value, receiver) {
console.log(setting ${key}!);
return Reflect.set(target, key, value, receiver);
}
});
get()方法

get方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(即this关键字指向的那个对象),其中最后一个参数可选。
var person = {
name: "张三"
};

var proxy = new Proxy(person, {
get: function(target, property) {
if (property in target) {
return target[property];
} else {
throw new ReferenceError("Property \"" + property + "\" does not exist.");
}
}
});

proxy.name // "张三"
proxy.age // 抛出一个错误
set()方法

set方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。
let validator = {
set: function(obj, prop, value) {
if (prop === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError('The age is not an integer');
}
if (value > 200) {
throw new RangeError('The age seems invalid');
}
}

// 对于满足条件的 age 属性以及其他属性,直接保存
obj[prop] = value;

}
};

let person = new Proxy({}, validator);

person.age = 100;

person.age // 100
person.age = 'young' // 报错
person.age = 300 // 报错
async和await

基本说明

async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
await命令

正常情况下,await命令后面是一个 Promise 对象。如果不是,会被转成一个立即resolve的 Promise 对象。
async function f() {
return await 123;
}

f().then(v => console.log(v))
// 123
class类

说明几个问题

constructor()

constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
class Point {
}

// 等同于
class Point {
constructor() {}
}
类继承中的super()

如果你要用类继承的话,里面一定要写super(),他是指定父类的this的,否则会报错
class A {}

class B extends A {
constructor() {
super();
}
}
浏览器加载

defer和async

<script src="path/to/myModule.js" defer></script>
<script src="path/to/myModule.js" async></script>
defer与async的区别是:defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。一句话,defer是“渲染完再执行”,async是“下载完就执行”。另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。
ES6的新语法

浏览器加载 ES6 模块,也使用<script>标签,但是要加入type="module"属性。浏览器对于带有type="module"的<script>,都是异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了<script>标签的defer属性。
<script type="module" src="./foo.js"></script>
ES6 模块也允许内嵌在网页中,语法行为与加载外部脚本完全一致。
<script type="module">
import utils from "./utils.js";
// other code
</script>
对于外部的模块脚本(上例是foo.js),有几点需要注意。

  • 代码是在模块作用域之中运行,而不是在全局作用域运行。模块内部的顶层变量,外部不可见。
  • 模块脚本自动采用严格模式,不管有没有声明use strict。
  • 模块之中,可以使用import命令加载其他模块(.js后缀不可省略,需要提供绝对 URL 或相对 URL),也可以使用export命令输出对外接口。
  • 模块之中,顶层的this关键字返回undefined,而不是指向window。也就是说,在模块顶层使用this关键字,是无意义的。
  • 同一个模块如果加载多次,将只执行一次。


最新回复 (0)
返回