判断对象是不是空对象
- 通过JSON.stringify()判断
- Object.keys()判断
const obj = {};
console.log(JSON.stringify(obj) == '{}') //true
console.log(Object.keys(obj).length == 0) //true
延迟加载js脚本的几种方式
- `<script>`标签添加`defer`属性
- `<script>`标签添加`async`属性
- 使用setTimeout定时器延时加载
- 将js脚本放在文章底部,使其可能最后加载执行
- 对文章的加载事件进行监听,等加载完成后,再创建`<script>`标签来引入js脚本
console.log(['1', '2', '3'].map(parseInt))
输出结果是[1, NAN, NAN]
参考链接:developer.mozilla.org/zh-CN/docs/…
typeof null
var
- var的作用域只有:全局作用域、函数作用域
- 预解析时,会把var和function声明的提前,赋值操作保留在原来位置。如果变量和函数同名,函数的声明更靠前
console.log(a);
var a = 1;
var a = function () {
console.log(2);
}
function a() {
console.log(3);
}
console.log(a);
// 输出
// f a() {...}
// f() {...}
// 预解析、执行过程如下
function a() { // 函数a声明提前
console.log(3);
}
var a
var a
console.log(a); //重复声明,不影响赋值操作
a = 1;
a = function () {
console.log(2);
}
console.log(a);
非匿名立即执行函数
var b = 10;
(function b() {
b = 20;
console.log(b) //为什么输出的是b函数
})()
解释:
`立即执行函数`在`预解析`时被分成两部分:函数声明和();
变量重名时,函数声明更靠前
所以在声明完函数后,会立即调用该函数,故输出b函数
Promise
- Promise的状态
- pending(等待中)
- fulfilled(已成功)
- rejected(已失败)
- Promise的方法(都是并行执行)
- Promise.all():所有都成功,结果是成功;有一个失败,就是失败
- Promise.allSettled(): 等所有都执行完,不管成功还是失败
- Promise.any():返回第一个成功的结果。如果所有promise都失败了,则返回所有失败的结果。
- Promise.race(): 有一个状态变了,promise的状态就跟着变
promise、try..catch()
new Promise((resolve, reject) => {
reject(1);
console.log(2);
resolve(3);
console.log(4);
}).then((res) => { console.log(res) })
.catch(res => { console.log('reject1') })
try {
new Promise((resolve, reject) => {
throw 'error'
}).then((res) => { console.log(res) })
.catch(res => { console.log('reject2') })
} catch (err) {
console.log(err)
}
// 输出结果是:2 4 reject1 reject2
// reject()或resolve()后,后面的代码还会运行
// Promise的状态只能被修改一次,如果后面还有修改状态的 会被忽略
// 一旦throw 'error', 后面的代码不会再执行
// 先reject('reject-1'); 再throw 'error': 会走Promise.catch,里面可以获取到reject的传参
// Promise里先resolve(),再throw 'error': 会走Promise.then。如果外面有try...catch, 也不会走catch
// Promise里只有throw 'error':会走Promise.catch,里面的可以获取到throw的信息
// Promise被reject()或throw 'error': 不会被外面的try...catch到,即使Promise没有.catch
async function f() {
try {
await new Promise((resolve, reject) => {
throw 'err'
})
} catch (e) {
console.log(e); // err 第二步
}
return await('hello');
}
const res = f();
console.log(res, 1); //log出promise对象 第一步
promise、async/await、Generator
- async await使用上更为简洁,将异步代码以同步的形式进行书写,是处理异步编程的最终方案
- promise编写代码相比Generator、async更为复杂,且可读性稍差
- Generator、async需要和promise对象搭配使用
- promise是es6, async await是es7
- promise和async await是专门用来处理异步的
- Generator并不是为异步而设计的,他还有其他功能(对象迭代、控制输出、部署Interator接口...)
- async await实质上是Generator的语法糖,相当于是会自动执行的Generator函数
- reject状态/throw报错的捕获:
- promise只能通过promise.catch()
- async await通过try-catch,还可以通过promise.catch()
- 把await语句放在try-catch里
- await后面的 Promise 对象再跟一个catch方法
- await后面的promise 如果rejected或报错,后面的代码不会继续执行
// 1
async function f() {
const result = await new Promise((resolve, reject) => {
resolve('resolve');
})
console.log(result); //resolve
console.log('111'); //111
}
f()
// 2
async function f() {
const result = await new Promise((resolve, reject) => {
reject('reject');
})
console.log(result); //不执行
console.log('111'); //不执行
}
f()
// 3
async function f() {
const result = await new Promise((resolve, reject) => {
reject('reject');
throw 'err'
})
console.log(result); //不执行
console.log('111'); //不执行
}
f()
// 4
async function f() {
try {
const result = await new Promise((resolve, reject) => {
resolve('resolve');
})
console.log(result); //resolve
console.log('111'); //111
} catch (e) {
console.log(e); // 不执行
}
}
f()
// 5
async function f() {
try {
const result = await new Promise((resolve, reject) => {
reject('reject');
})
console.log(result); //不执行
console.log('111'); //不执行
} catch(e) {
console.log(e); // reject
}
}
f()
// 6
async function f() {
try {
const result = await new Promise((resolve, reject) => {
throw 'err'
})
console.log(result); //不执行
console.log('111'); //不执行
} catch (e) {
console.log(e); // err
}
}
f()
// 7
async function f() {
try {
const result = await new Promise((resolve, reject) => {
resolve('resolve');
}).then((res) => {
console.log(res); //resolve
return res;
})
.catch((e) => {
console.log(e); //不执行
})
console.log(result); //resolve
console.log('111'); //111
} catch (e) {
console.log(e); // 不执行
}
}
f()
// 8
async function f() {
try {
const result = await new Promise((resolve, reject) => {
reject('reject');
}).then((e) => {
console.log(e); //不执行
})
.catch((e) => {
console.log(e); //reject
return e;
})
console.log(result); //reject
console.log('111'); //111
} catch (e) {
console.log(e); // 不执行
}
}
f()
// 9
async function f() {
try {
const result = await new Promise((resolve, reject) => {
throw 'err'
}).then((e) => {
console.log(e); //不执行
})
.catch((e) => {
console.log(e); //err
})
console.log(result); //undefined
console.log('111'); //111
} catch (e) {
console.log(e); // 不执行
}
}
f()
Promise嵌套
// 第一题
// P1
new Promise(resolve => {
console.log('P1 resolve')
resolve()
}).then(() => {
console.log('P1 then 1')
// P2
new Promise(resolve => {
console.log('P2 resolve')
resolve()
}).then(() => {
console.log('P2 then 1')
}).then(() => {
console.log('P2 then 2')
})
}).then(() => {
console.log('P1 then 2')
})
// P1 resolve
// P1 then 1
// P2 resolve
// P2 then 1
// 注意:此时 P1 的第一个 then 就算是执行完毕了,下面会执行 P1 的第二个 then
// P1 then 2
// P2 then 2
// 第二题
// P1
new Promise(resolve => {
console.log('P1 resolve')
resolve()
}).then(() => {
console.log('P1 then 1')
// P2
return new Promise(resolve => {
console.log('P2 resolve')
resolve()
}).then(() => {
console.log('P2 then 1')
}).then(() => {
console.log('P2 then 2')
})
}).then(() => {
console.log('P1 then 2')
})
// P1 resolve
// P1 then 1
// P2 resolve
// P2 then 1
// 注意:这里用了 return ,所以 P1 的第一个 then 执行完毕得等待 P2 完整执行完才算是执行完,才能 return 一个同步返回值回去
// 所以这里的结果跟上个例子不一样了
// P2 then 2
// P1 then 2
// 第三题
new Promise(resolve => {
console.log('P1 resolve')
resolve()
}).then(async () => {
console.log('P1 then 1')
// P2
// 也等同于 return await P2
await new Promise(resolve => {
console.log('P2 resolve')
resolve()
}).then(() => {
console.log('P2 then 1')
}).then(() => {
console.log('P2 then 2')
})
}).then(() => {
console.log('P1 then 2')
})
// P1 resolve
// P1 then 1
// await 同上面的return
// P2 resolve
// P2 then 1
// P2 then 2
// P1 then 2
async await
执行到await时,被等待的表达式会立即执行,await下面的所有代码会推送进微任务队列。
queueMicrotask(() => {...}):Window 或 Worker的接口,将传入的函数加入微任务队列。遇到queueMicrotask()会直接执行,将函数放入微任务
async function foo() {
console.log('11');
await Promise.resolve().then(resolve => {
console.log("1");
});
console.log(3);
}
foo();
console.log('33');
//输出:11,33, 1, 3
// 第一题
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
}
async function async2() {
console.log('async2');
new Promise((resolve, reject) => {
resolve(1);
console.log('async2---');
});
}
async1();
new Promise(function (resolve) {
console.log("promise1");
resolve();
}).then(function () {
console.log("promise2");
});
// 输出结果
// async1 start
// async2
// async2-- -
// promise1
// async1 end
// promise2
// 第二题
new Promise((resolve, reject) => {
console.log("promise1")
resolve()
}).then(() => {
console.log("then11")
new Promise((resolve, reject) => {
console.log("promise2")
resolve()
}).then(() => {
console.log("then21")
}).then(() => {
console.log("then23")
})
}).then(() => {
console.log("then12")
})
// 输出
// promise1
// then11
// promise2
// then21
// then12
// then23
// 第三题
new Promise((resolve, reject) => {
console.log("promise1")
resolve()
}).then(() => {
console.log("then11")
new Promise((resolve, reject) => {
console.log("promise2")
resolve()
}).then(() => {
console.log("then21")
}).then(() => {
console.log("then23")
})
}).then(() => {
console.log("then12")
})
new Promise((resolve, reject) => {
console.log("promise3")
resolve()
}).then(() => {
console.log("then31")
})
// 输出
// promise1
// promise3
// then11
// promise2
// then31
// then21
// then12
// then23
判断是宏任务还是微任务
- 看发起源是谁:宿主(浏览器、node)发起的是宏任务,js引擎发起的是微任务
- setTimeout里的回调函数是一个宏任务
- 参考链接:blog.csdn.net/NancyFyn/ar…
数组方法
- splice(): 改变原数组,就地移除或者替换已存在的元素和/或添加新的元素。
//start必填,其它参数可选
//item1、...、itemn:从 start 开始要加入到数组中的元素。
splice(start, deleteCount, item1, item2, /* …, */ itemN)
- slice(): 返回一个新数组,这一对象是一个由 start 和 end 决定的原数组的浅拷贝(包括 start,不包括 end)
- sort(): 改变原数组。
- join()
数组去重
- Array.from(new Set(arr))
- reduce
const resultArr = arr.reduce((accumulator, currentValue) => {
if (!accumulator.includes(currentValue)) {
return [...accumulator, currentValue];
}
return accumulator;
}, []);
- filter + indexof/findIndex
function unique(arr) {
return arr.filter((item, index, array) => {
return array.indexOf(item) === index;
});
}
Map
- map.has()
- map.get()
- map.set()
- map.valuse()
- Array.from(map.values())
call、apply、bind
apply(thisArg, argsArray)
call(thisArg, arg1, arg2, /* …, */ argN)
bind(thisArg, arg1, arg2, /* …, */ argN) //返回一个新函数