es6常用方法
普通引入与* as引入的区别
import * as xxx from ‘xxx’:
会将若干export导出的内容组合成一个对象返回;
import xxx from ‘xxx’:
只会导出这个默认的对象作为一个对象
let
(1)基本用法–块级作用域
原本JS只有函数作用域,没有块级作用域。ES6 新增了let变量声明命令,声明的变量仅在块级作用域内有效
for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
for (let i = 0; i < 3; i++) { let i = 'abc'; console.log(i); } // abc // abc // abc
(2)不存在变量提升
之前由于JS的预处理机制,var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。
let命令所声明的变量一定要在声明后使用,否则报错,因为预处理机制只找var和function
(3)会有暂时性死区、不允许重复声明
let 和 const 声明的变量不存在变量提升,其作用域都是块级作用域,凡是在声明变量之前使用变量就会报错
所以,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”
(4)块级作用域与函数声明
考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句
const
(1)基本用法
const声明一个只读的常量。一旦声明,常量的值就不能改变,且只在声明所在的块级作用域内有效。
这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
(2)其他同let
不存在变量提升、会有暂时性死区、不允许重复声明
展开运算符
合并数组
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5, 6];
结果返回1,2,3,4,5,6
合并对象
const obj1 = {1, 2, 3};
const obj2 = [...obj1, 4, 5,6];
结果返回1,2,3,4,5,6
最后补充一下:
数组另一种合并方法:concat()
对象另一种合并方法:assign()
箭头函数
箭头函数
var fn = (a1, b2) => { return a1 + b2; }
普通函数
var fn = function(a1, b2) {
return a1+ b2;
};
参数:
如果箭头函数没有参数,直接写一个空括号即可。
如果箭头函数的参数只有一个,也可以省去包裹参数的括号。
如果箭头函数有多个参数,将参数依次用逗号(,)分隔,包裹在括号中即可。
函数体:
一句代码直接写不用包对象
多句代码行用对象包着
箭头函数的缺点:
箭头函数中无原型,this、arguments
在原型上使用箭头函数:箭头函数中的this不是指向当前,而是根据变量查找规则找去全局作用域
注意事项:
不要在最外层定义箭头函数,因为在函数内部操作this会很容易污染全局作用域。最起码在箭头函数外部包一层普通函数,这样箭头函数就会继承外层函数的this,从而将this制在可见的范围内;
数组新增方法
forEach()
会遍历数组, 循环体内没有返回值
forEach()循环不会改变原来数组的内容, forEach()有三个参数, 第一个参数是当前元素, 第二个参数是当前元素的索引,
第三个参数是当前元素所属的数组.
let array = [1, 2, 3, 4];
array.forEach((item, index, arr) => {
console.log(item);
});
map()
的主要作用, 其实是创建一个新的数组, map()的参数和forEach()是一样的
let array = [1, 2, 3, 4 ,5];
let temp = array.map((item, index, arr) => {
return item + 1;
});
console.log(temp);
console.log(array);
只有当arr为基本数据类型时,map方法才不会改变原始数组,arr为引用类型时,还是会改变原数组的
// 1、基本数据类型
let arr=[1,2,3,4,5]
let newArr=arr.map((item) => item*2)
console.log(arr); // [1,2,3,4,5]
console.log(newArr);//[2, 4, 6, 8, 10]
// 2、引用数据类型
let arr = [{ key1: '111' }, { key1: '222' }]
let newArr=arr.map((item) => {
item.key2='ceshi';
return item;
})
console.log(arr);
// [{key1: "111", key2: "ceshi"},{key1: "222", key2: "ceshi"}]
console.log(newArr);
// [{key1: "111", key2: "ceshi"},{key1: "222", key2: "ceshi"}]
filter()
主要是过滤的, 用来过滤数组中不满足条件的元素, 把满足条件的元素放到新的数组里, 并且不会改变原数组.参数也跟foreach一样
let array = [1, 2, 3, 4, 5];
let temp = array.filter((item, index, arr) => {
return item > 3;
});
console.log(temp);
console.log(array);
every()
的作用, 它会遍历数组, 在循环体内写条件, 如果每一项都是true, 就会返回true, 只要有一个是false, 就会返回false,参数同上
let array = [1, 2, 3, 4, 5];
let bo = array.every((item, index, arr) => {
return item > 2;
});
console.log(bo);
reduce()
跟其他几个方法不一样, 它有4个参数, 按顺序分别是 上一次的值, 当前的值, 当前值的索引, 数组
let array = [1, 2, 3, 4, 5];
let total = array.reduce((a, b) => {
return a + b;
});
console.log(total); // 15
flat()
默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将flat()方法的参数写成一个整数,表示想要拉平的层数,默认为1。
[1, 2, [3, [4, 5]]].flat()
// [1, 2, 3, [4, 5]]
[1, 2, [3, [4, 5]]].flat(2)
// [1, 2, 3, 4, 5]
字符串新增方法
repeat()
方法复制指定次数字符串。
var str = "Runoob";
str.repeat(2);
RunoobRunoob
模板字符串
用用反引号(`)标识,可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
模板字符串中嵌入变量,需要将变量名写在${}之中
includes()
方法用来判断一个数组是否包含一个指定的值,如果是返回 true,否则false。
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(3, 3); // false
startsWith()
:返回布尔值,表示参数字符串是否在原字符串的头部。
var str = "Hello world, welcome to the Runoob.";
var n = str.startsWith("Hello");
输出结果:true
endsWith()
:返回布尔值,表示参数字符串是否在原字符串的尾部。
var str = "Hello world, welcome to the Runoob.";
var n = str.endsWith("Hello");
输出结果:false
matchAll()
返回一个正则表达式在当前字符串的所有匹配
新增对象方法
Object.is()
它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
Object.is('foo', 'foo')
// true
Object.is({}, {})
// false
Object.assign()
方法用于对象的合并
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
Object.getOwnPropertyDescriptors()
方法,返回指定对象所有自身属性(非继承属性)的描述对象。
const obj = {
foo: 123,
get bar() { return 'abc' }
};
Object.getOwnPropertyDescriptors(obj)
Object.keys()
方法,返回一个数组,每一项是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。
var obj = { foo: 'bar', baz: 42 };
Object.keys(obj)
// ["foo", "baz"]
Object.values()
方法返回一个数组,每一项是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
const obj = { foo: 'bar', baz: 42 };
Object.values(obj)
// ["bar", 42]
Object.entries()
方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。
const obj = { foo: 'bar', baz: 42 };
Object.entries(obj)
// [ ["foo", "bar"], ["baz", 42] ]
Object.fromEntries()
方法是Object.entries()的逆操作,用于将一个键值对数组转为对象。
Object.fromEntries([
['foo', 'bar'],
['baz', 42]
])
// { foo: "bar", baz: 42 }
async是Generator 函数的语法糖让异步操作更加方便
基本用法:
// 函数声明
async function foo() {}
// 函数表达式
const foo = async function () {};
// 对象的方法
let obj = { async foo() {} };
obj.foo().then(...)
// Class 的方法
class Storage {
constructor() {
this.cachePromise = caches.open('avatars');
}
async getAvatar(name) {
const cache = await this.cachePromise;
return cache.match(`/avatars/${name}.jpg`);
}
}
const storage = new Storage();
storage.getAvatar('jake').then(…);
// 箭头函数
const foo = async () => {};
Promise 对象
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大,就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
Promise有三个状态:
pending(等待)、resolve(完成)、 reject(拒绝)
两种状态改变方式:
pending => resolve,
pending => reject
Promise对象有以下两个特点:
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
优点:
(1)可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
(2)提供统一的接口,使得控制异步操作更加容易。
缺点:
(1)无法取消Promise,一旦新建它就会立即执行,无法中途取消。
(2)如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
(3)当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。 所以处理异步可以选择Generator
解决的问题:
原始方法
//以往回调方式
函数1(function(){
//代码执行...(ajax1)
函数2(function(){
//代码执行...(ajax2)
函数3(function(data3){
//代码执行...(ajax3)
});
...
});
});
```bash
//Promise回调方式:链式调用,可构建多个回调函数。
//例如请求一个ajax之后,需要这个拿到这个ajax的数据去请求下一个ajax
promise().then().then()...catch()
promise方法(解决回调地狱)
//首先要创建Promise实例
let promise = new Promise( (resolve, reject) => {
//执行相应代码并根据情况调用resolve或reject
if(a>30){
resolve(a)
//将promise的状态设置为成功
}else{
reject(a)
//将promise的状态设置为失败
}
...
})
//在promise的then方法中执行回调
promise.then(function(value){
//第一个参数是返回resolve时,回调执行的函数
console.log(value)
},function(resson){
//第二个是回调返回reject时,回调执行的函数
console.log(reason)
}
}
resolve: then方法的第一个参数,通常作为事件成功的回调函数
reject: then方法的第二个参数,通常作为事件失败的回调函数,也可以作为catch的参数出现
传递参数,接收时成功用value接收失败用reason接收
promise方法
Promise.resolve(value)
value:成功的数据或promise对象
作用:返回一个成功/失败的promise对象
//如果传入的参数是非promise对象,输出结果则是成功的promise对象
let p = Promise.resolve(521);
console.log(p)
//Promise {<fulfilled>: 521}成功的值
//如果传入的参数是promise对象,输出结果则根据参数来决定结果
let p2 = Promise.resolve(new Promise((resolve,reject)=>{
//resolve('ok')
reject('error')
}));
p2.catch(reason=>{
console.log(reason)
})//里面是reject,则输出对应值error
Promise.reject(reason)
reason:失败的数据或原因
作用:返回一个失败的promise对象
//不论传入什么类型的参数返回结果都是失败的
let p = Promise.reject('error');
console.log(p)
Promise.all(promises)
promises包含n个promise的数组
作用:返回一个新的Promise对象,只有当所有的结果是成功才会成功,只要有一个失败就失败
let p1 = new Promise((resolve,reject)=>{
resolve('ok')
})
let p2 = new Promise((resolve,reject)=>{
reject('error')
})
let p3 = Promise.resolve('hao')
const result = Promise.all([p1,p2,p3])
console.log(result)
//有一个失败就失败reject
Promise.any(promises)
promises包含n个promise的数组
作用:返回一个新的Promise对象,只有当所有的结果是失败才会失败,只要有一个成功就成功
let p1 = new Promise((resolve,reject)=>{
resolve('ok')
})
let p2 = new Promise((resolve,reject)=>{
reject('error')
})
let p3 = Promise.resolve('hao')
const result = Promise.any([p1,p2,p3])
console.log(result)
//有一个成功就成功fulfilled
Promise.race(promises)
promises包含n个promise的数组
作用:返回一个新的Promise对象,第一个完成的状态就代表最终的状态
let p1 = new Promise((resolve,reject)=>{
resolve('ok')
})
let p2 = new Promise((resolve,reject)=>{
reject('error')
})
let p3 = Promise.resolve('hao')
const result = Promise.race([p1,p2,p3])
console.log(result)
//fulfilled成功
改变promise对象状态
三种方式
let p = new Promise((resolve,reject)=>{
resolve('ok')//pendding=>fulfilled(resolved)
reject('error')//pending=>rejected
throw('出问题啦')//rejected
})
console.log(p)
中断promise链
插入这个
return new Promise(()=>{})
手撕promise
(function (window) {
// 状态常量
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
function Promise(excutor) {
const that = this
that.status = PENDING
that.data = undefined
that.callbacks = [] // 每个元素的类型如下:{onResolved:xxx,onRejected:xxxx}
// 下面两个方法的作用就是改变状态,执行回调
function resolve(value) {
if(that.status !== PENDING){
return
}
that.status = RESOLVED
that.data = value
if(that.callbacks.length>0){
that.callbacks.forEach(callbackObj => {
// 这个回调模拟了一些异步任务,不过正常Promise不是通过setTimeout宏任务执行的
setTimeout(() => {
callbackObj.onResolved(value)
},0);
});
}
}
function reject(reason) {
if(that.status !== PENDING){
return
}
that.status = REJECTED
that.data = reason
if(that.callbacks.length>0){
that.callbacks.forEach(callbackObj => {
// 这个回调模拟了一些异步任务,不过正常Promise不是通过setTimeout宏任务执行的
setTimeout(() => {
callbackObj.onRejected(reason)
},0);
});
}
}
try {
excutor(resolve,reject)
} catch (error) {
reject(error)
}
}
Promise.prototype.then = function (onResolved,onRejected) {
const that = this
// then方法的作用就是收集回调(onResolved,onRejected)
// 在then方法中需要对onResolved,onRejected给默认值(就是没有指定onResolved,onRejected回调的时候)
// 指定默认的失败的回调(如果没有指定onRejected回调的话,实现异常的传递)
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
// 向后传递成功的value
onResolved = typeof onResolved === 'function' ? onResolved : value => value
// 返回一个promise对象,而这个promise的结果就是onResolved,onRejected的执行结果
return new Promise((resolve,reject) => {
if(that.status === PENDING){
// 当前状态为pending时,收集回调到callbacks数组中
that.callbacks.push({
onResolved () {
// onResolved(that.data)
try {
const result = onResolved(that.data)
if (result instanceof Promise) {
result.then(resolve, reason)
} else {
// 2情况
resolve(result)
}
} catch (error) {
// 1情况
reject(error)
}
},
onRejected () {
try {
const result = onRejected(that.data)
if (result instanceof Promise) {
result.then(resolve, reason)
} else {
// 2情况
resolve(result)
}
} catch (error) {
// 1情况
reject(error)
}
}
})
} else if(that.status === RESOLVED){
// 此时状态已经改变,这时需要立即执行回调
setTimeout(() => {
// 根据onResolved(that.data)返回的结果,给return 新的promise的设置状态
// onResolved(that.data)如果异常的话 return的promise的状态为rejected
// onResolved(that.data)返回的如果不是一个promise的话, return的promise的状态为resolved value就是onResolved(that.data)返回值
// onResolved(that.data)返回的如果是一个promise的话, return的promise的状态就是onResolved(that.data)返回的状态
try {
const result = onResolved(that.data)
if(result instanceof Promise){
result.then(
value => resolve(value),
reason => reject(reason)
)
} else {
resolve(result)
}
} catch (error) {
reject(error)
}
});
} else {
setTimeout(() => {
try {
const result = onRejected(that.data)
if(result instanceof Promise){
result.then(
value => resolve(value),
reason => reject(reason)
)
} else {
resolve(result)
}
} catch (error) {
reject(error)
}
});
}
})
}
Promise.prototype.catch = function (onRejected) {
// Promise.prototype.then(undefined,onRejected)
return this.then(undefined, onRejected)
}
Promise.resolve = function (value) {
return new Promise((resolve,reject)=>{
// 返回promise的时候需要注意value是不是 promise对象,如果是的话,那返回的promise的状态就是由value的状态决定
if(value instanceof Promise){
value.then(resolve,reject)
} else {
resolve(value)
}
})
}
Promise.reject = function (reason) {
// Promise.reject不会处理像上面resolve函数那样处理传进来的是promise对象的问题
return new Promise((resolve,reject)=>{
reject(reason)
})
}
Promise.all = function (promises) {
let count = 0;
let values = new Array(promises.length)
return new Promise((resolve,reject)=>{
promises.forEach((p,index) => {
Promise.resolve(p).then(
value => {
count++
values[index] = value
// 这个地方等所有的then执行完再改变状态
if(count == promises.length){
resolve(values)
}
},
reason => reject(reason)
)
});
})
}
Promise.race = function (promises) {
return new Promise((resolve,reject)=>{
promises.forEach(p => {
Promise.resolve(p).then(
value => resolve(value),
reason => reject(reason)
)
});
})
}
window.Promise = Promise
})(window)