1 Date.now()
Date.now()是毫秒为单位
2 console
2.1 console.dir
输出一个对象或者一个值的详细信息,与console.log区别是后者可以一次输出多个,但是console.dir一次只能输出一个
2.2 console.warn
以警告的形式输出
2.3 console.table
将json数据按照表格形式输出
2.4 console.time和console.timeEnd
计算console.time和console.timeEnd之间的时间(单位:ms)
forExample:
console.time('计时器1:')
for(let i = 0; i < 10000; i++){
var a = 1
}
console.timeEnd('计时器1:')
3 数值比较
- 数字 == 字符串 (将字符串转变为数字,然后进行对比)
- 数字 == 布尔 (将布尔转变为数字,然后进行对比)
- 字符串 == 布尔 (将二者都转变为数字在进行比较)
- 对象 == 数字 (对象转变为数字**,然后进行比较)
- 对象 == 布尔 (将二者都转变为数字,然后进行比较)
- 对象 == 字符串 (将对象转变为字符串,然后进行比较)
规律:除了对象和字符串比较的时候,把对象转变为字符串外,剩余只要类型不同,都是先转变为数字类型,然后进行比较。
栗子:
5 == true // false
1 == true // ture
if(1) {
console.log('可以打印')
}
if(5) {
console.log('可以打印')
}
需要注意的是,上面的例子中,虽然5 == true结果为false, 但是如果是在if语句中,即:if(5) 此时,会将5转变为true。
4 栈内存和堆内存
- 占内存:主要存放基本数据类型(string,number,boolean,undefined,null等)以及引用数据类型的指针等。
- 堆内存:主要存放引用数据类型。
5 数组扁平化
let arr = [1, [2, [3, [4, 5]]], 6];
5.1 正则
let str = JSON.stringify(arr)
arr = str.replace(/(\[\]))/g, '').split(',')
5.2 递归
let result = [];
let fn = function(arr) {
for(let i = 0; i < arr.length; i++) }{
let item = arr[i];
if (Array.isArray(arr[i])){
fn(item);
} else {
result.push(item);
}
}
}
5.3 flat
let res = arr.flat(Infinity)
6 requestAnimationFrame
js中比定时器动画更好的执行方式,通常为每秒60次。
接收一个回调函数作为参数,回调函数执行次数通常与浏览器屏幕刷新次数相匹配。
为了提高性能和电池寿命,因此在大多数浏览器里,当requestAnimationFrame() 运行在后台标签页或者隐藏的 里时,requestAnimationFrame() 会被暂停调用以提升性能和电池寿命。
7 JSON.stringify()注意点
JSON.stringify(arr)并不是对所有的值都能有效处理,例如,它会把正则变为空对象,函数/undefined/Symbol都会变为null, 日期格式变为字符串后,基于parse也回不到对象格式了。
8 mouseover和mouseenter区别
mouseenter: 默认阻止了事件的冒泡传播。从父元素进入子元素,从子元素,进入父元素,父元素的enter和leave都不会触发。
mouseover: 从父元素移动到子元素,子元素和父元素都会触发over,从子元素移动到父元素,子元素和父元素都会触发out事件。
9 宏任务和微任务
js中的异步任务可以分为宏任务(macroTask)和微任务(microTask)。 常见的宏任务:script(整体代码), setTimeout, setInterval, setImmediate, 微任务:Promises,process.nextTick(其为事件循环设置一项任务,node.js会在下次事件循环调响应时调用回调函数)。
同步任务,微任务,宏任务执行顺序
顺序 : 先执行同步代码,遇到宏任务则将宏任务放入宏任务队列中,遇到微任务则将微任务放入微任务队列中,同步代码执行完毕以后,再执行所有的微任务。微微任务,然后在执行宏任务。
因此需要注意的是
微任务的执行效率要快于宏任务。
10 数值交换
let a = 1, b = 2;
10.1 异或
a = a ^ b;
b = a ^ b;
a = a ^ b;
10.2 求和
a = a + b;
b = a - b;
a = a - b;
10.3 解构
[a, b] = [b, a]
11 另类小数取整
let a = 10.5 | 0
let b = ~~10.5
12 判断奇偶数
const a = 3;
let flag = !!(a & 1) //奇数为true,偶数为false
console.log(flag) // true
13 格式化金钱
const filterMoney = num => num.toString().replace(/(?=(\B)(\d{3})+$)/g, ",");
const money = filterMoney(27898989); // ‘27,898,989’
14 随机打乱数组
let arr = [1,2,3,4,5]
let res = arr.sort(() => Math.random() - .5)
15 new Function
let sum = new Function('a', 'b', 'return a + b');
console.log(sum(1,3))
16 Object.defineProperty和Proxy
Object.defineProperty(obj,key,handler)主要有三个:
- 不能监听数组的变化
- 必须遍历对象的每个属性
- 必须深层遍历嵌套的对象
Proxy(obj, handler)
- 针对对象:针对整个对象,而不是对象的某个属性。
- 支持数组:不需要对数组的方法进行重载,省去了众多 hack。
- 嵌套支持: get 里面递归调用 Proxy 并返回。
其他方面:
优势:Proxy 的第二个参数可以有 13 种拦截方法,比 Object.defineProperty() 要更加丰富,Proxy 作为新标准受到浏览器厂商的重点关注和性能优化,相比之下 Object.defineProperty() 是一个已有的老方法。
劣势:Proxy 的兼容性不如 Object.defineProperty() (caniuse 的数据表明,QQ 浏览器和百度浏览器并不支持 Proxy,这对国内移动开发来说估计无法接受,但两者都支持 Object.defineProperty()),不能使用 polyfill 来处理兼容性
17 Map和Object
ES6提供了Map数据结构,它类似于对象,也是键值对的集合。
object只能接收字符串作为键名,但是map可以接收各种类型的值(包括对象)作为键值。
17.1 Map实例的属性和方法如下:
- size:获取成员的数量
- set:设置成员 key 和 value
- get:获取成员属性值
- has:判断成员是否存在
- delete:删除成员
- clear:清空所有
const map = new Map(['a',1],['b',2]);
map.set('a', 100);
map.size // 2
map.get('a') // 100
map.has('a') // true
map.delete('a')
map.has('a') // false
map.clear()
17.2 Map实例的遍历方法
keys():返回键名的遍历器。 values():返回键值的遍历器。 entries():返回所有成员的遍历器。 forEach():遍历 Map 的所有成员。
const map = new Map(['a',1],['b',2]);
for (let key of map.keys()) {
console.log(key);
}
// "a"
// "b"
for (let value of map.values()) {
console.log(value);
}
// 1
// 2
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
// 'a' 1
// 'b' 2
map.forEach((item, i) => {
console.log(item, i)
})
// 1 "a"
// 2 "b"
18 NaN,indexOf, includes
NaN 不等于 NaN,这是事实。
但是如果一个数组let arr = [1, 2, NaN], 如果arr.includes(NaN)为true, arr.indexOf(NaN)为-1。
19 求幂Math.pow(x,y) 和 **
let a = Math.pow(2, 3) // 8
let b = 2 ** 3 // 8
20 Object.entries()
该方法会将某个对象的可枚举属性与值按照二维数组的方式返回。(如果目标对象是数组,则会将数组的下标作为键值返回)
let arr = [1,2,3]
Object.entries(arr) // [['0',1], ['1',2], ['2',3]]
let obj = {"a" : 1, "b": 2}
Object.entries(obj) // [['a',1], ['b', 2]]
21 for...in于for...of
21.1 for...of
遍历可迭代对象(包括数组、Set 和 Map 结构、arguments 对象、DOM NodeList 对象、字符串等)
// 数组
let arr = ['a', 'b', 'c'];
for (let v of arr) {
console.log(v);
}
// 'a' 'b' 'c'
// 字符串
let str = 'abc;
for (let v of str) {
console.log(v);
}
// abc
// 类数组对象
let obj = {
0: 'mazey',
1: 'luna',
2: 'cherrie',
length: 3
};
// 需使用Array.from转换成可迭代对象
for (let v of Array.from(obj)) {
console.log(v);
}
// mazey luna cherrie
// Set
let s = new Set(['a', 'b', 'c']);
for (let v of s) {
console.log(v);
}
// 'a' 'b' 'c'
// Map
let m = new Map([
['0', 'a'],
['1', 'b'],
['2', 'c']
]);
for (let [i, v] of m) {
console.log(v);
}
// 'a' 'b' 'c'
// DOM NodeList
let domList = document.querySelectorAll('li');
for (let v of domList) {
console.log(v.innerText);
}
// mazey luna cherrie
21.2 for...in和for...of区别
- for…in 遍历键名,for…of 遍历键值
let arr = ['mazey', 'luna', 'cherrie'];
for (let k in arr) {
console.log(k);
}
// 0 1 2
for (let v of arr) {
console.log(v);
}
// mazey luna cherrie
- for…in 会把对象上手动添加的属性和原型上的属性暴露出来。
let obj = {
0: 'mazey',
1: 'luna',
2: 'cherrie',
length: 3
};
obj.name = 'objName';
for (let k in obj) {
console.log(k);
}
// 0 1 2 length name
for (let v of Array.from(obj)) {
console.log(v);
}
// mazey luna cherrie
21.3 for...of和数组forEach区别
-
相对于数组自带的 forEach 方法,for…of 可以与 break、continue 和 return 配合使用。
-
正确识别32位 UTF-16 字符。