flat数组降维
利用递归循环和数组合并
Array.prototype.adFlat = function(deep) {
return deep > 0 ? this.reduce((total, item, index) => {
return total.concat(Array.isArray(item) ? item.adFlat(deep - 1) : item)
}, []) : this.slice()
}call\apply\bind指向修改
利用this的特性,将要执行的方法放到指定的this上,然后执行
//call\apply
Function.prototype.adCall = function() {
//如果是apply,将 [pointer, ...args] 改为 [pointer, args]
let [pointer, ...args] = [...arguments], //将传入参数解析成指针和其他参数
fn = Symbol(); //创建独立名称
pointer = Object(pointer) || window; //将传入指针转换成实例对象
pointer[fn] = this; //向创建对象添加fn独立方法
let rel = pointer[fn](...args); //将执行结果赋值
delete pointer[fn]; //删除之前添加进指针对象的方法
return rel; //返回执行结果
}
//bind
Function.prototype.adBind = function(pointer, ...args) {
return (...newagrs) => this.call(pointer, ...args, ...newagrs) //方法返回一个方法,传入两次传入的参数
}new对象实例化
创建一个新对象,这个对象的原型指向构造函数的原型->在新对象上执行这个构造函数->返回新对象;与Object.create的差别在于,new会执行构造函数
function _new(fn, ...args) {
let obj = {}; // 创建一个空对象
obj.__proto__ = fn.prototype; // 空对象原型指向构造函数原型
fn.call(obj, ...args); // 改变指向并执行构造函数
return obj; // 返回新对象
}instanceOf实例判断
由于instanceOf的判断是会往原型链顶层走的,所以我们需要使用递归或者循环来往原型顶层走,通过实例对象的
__proto__和对象的原型prototype进行比对
function instanceOf(leftVal, rightVal) {
if (typeof leftVal != 'object' || leftVal === null) return false;
let leftPro = leftVal.__proto__, // 获取实例化内容的原型
rightPro = rightVal.prototype; // 获取原型
while (true) { // 深度向上寻找原型,直到顶层Object.prototype
if (leftPro === null) return false;
if (leftPro === rightPro) return true;
leftPro = leftPro.__proto__
}
}JSON.parse解析
利用eval函数
function parse (json) {
// 此处的括号是为了表明内部执行内容为一个整体,就像箭头函数简写返回一个对象也需要括号包裹一样
return eval("(" + json + ")");
}await/async异步自动执行队列
await与async实际上就是generator函数的语法糖,所以此处使用generator实现。generator本身拥有中断递进的功能,所以与promise配合,通过next的传参性质,使用递归执行generator内容即可
// 此处伪代码并未考虑抛错,如需了解请看下一个代码块
function generatorToAsync(generatorFn) {
return function() {
return new Promise((resolve, reject) => {
const g = generatorFn()
const handler = (res) => {
const cb = g.next(res).value
if (typeof cb.then === 'function') {
cb.then(res => handler(res))
} else {
resolve(res)
}
}
g.next().value.then(handler)
})
}
}
function fn(nums) {
return new Promise(resolve => {
setTimeout(() => {
resolve(nums * 2)
}, 1000)
})
}
const asyncFn = generatorToAsync(function*() {
const num1 = yield fn(1)
console.log('1 end');
const num2 = yield fn(num1)
console.log('2 end');
const num3 = yield fn(num2)
console.log('3 end');
return num3
})
asyncFn().then(res => console.log(res)) // 3秒后输出 8较为完善的实现
function generatorToAsync(generatorFn) {
return function() {
const gen = generatorFn.apply(this, arguments) // gen有可能传参
// 返回一个Promise
return new Promise((resolve, reject) => {
function go(key, arg) {
let res
try {
res = gen[key](arg) // 这里有可能会执行返回reject状态的Promise
} catch (error) {
return reject(error) // 报错的话会走catch,直接reject
}
// 解构获得value和done
console.log(res);
const {
value,
done
} = res
if (done) {
// 如果done为true,说明走完了,进行resolve(value)
return resolve(value)
} else {
// 如果done为false,说明没走完,还得继续走
// value有可能是:常量,Promise,Promise有可能是成功或者失败
return Promise.resolve(value).then(val => go('next', val), err => go('throw', err))
}
}
go("next") // 第一次执行
})
}
}is值相同对比
利用
1/0===Infinity与1/-0===-Infinity的特性区分正负0相同判断;利用NaN永不与NaN相等的特性判断NaN
function is(x, y) {
if (x === y) {
// 防止 -0 和 +0
return x !== 0 || 1 / x === 1 / y
}
// 防止NaN
return x !== x && y !== y
}
console.log(is(0, -0)); // false