科里化
function curry(func) {
return function curriedFn(...args) {
if (args.length < func.length) {
return function () {
return curriedFn(args.concat(Array.from(arguments)))
}
}
}
}
组合函数
function compose(...args) {
return function (value) {
return args.reverse().reduce(function (acc, fn) {
return fn(acc)
}, value)
}
}
new实现原理
function _new(Func, ...args) {
let obj = Object.create(Func.protoType);
let result = Func.call(obj, ...args);
if ((result !== null && typeof result === 'object') || (typeof result === 'function')) {
return result;
}
return obj;
}
深度克隆
function _type(value) {
return Object.prototype.toString.call(value);
}
function _deepClone(obj) {
if (obj === null) return null;
if (typeof obj !== 'object') return obj;
if (_type(obj) === '[object RegExp]') return new RegExp(obj);
if (_type(obj) === '[object Date]') return new Date(obj);
let newObj = new obj.constructor;
for (let key in obj) {
if (!obj.hasOwnProperty(key)) break;
newObj[key] = _deepClone(obj[key]);
}
return newObj;
}
发布订阅
class Sub {
constructor() {
this.$pond = [];
}
add(fn) {
let flag = this.$pond.some((item) => {
return item === fn
});
!flag && this.$pond.push(fn)
}
remove(fn) {
let $pond = this.$pond;
for (let i = 0; i < $pond.length; i++) {
let item = $pond[i];
if (item === fn) {
$pond[i] = null;
}
}
}
fire(...args) {
let $pond = this.$pond;
for (let i = 0; i < $pond.length; i++) {
let item = $pond[i];
if (typeof item !== "function") {
$pond.splice(i, 1);
i--;
continue;
}
item.call(this, ...args)
}
}
}
promise
class MyPromise {
constructor(executor) {
this.status = 'pending';
this.value = undefined;
this.resolveArr = [];
this.rejectArr = [];
let change = (status, value) => {
if (this.status !== 'pending') return;
this.value = value;
this.status = status;
let fnArr = status === 'resolved' ? this.resolveArr : this.rejectArr;
fnArr.forEach(item => {
if (typeof item !== 'function') return;
item(this.value);
});
};
let resolve = result => {
if (this.resolveArr.length > 0) {
change('resolved', result);
return;
}
let delayTimer = setTimeout(_ => {
change('resolved', result);
clearTimeout(delayTimer);
}, 0);
};
let reject = reason => {
if (this.rejectArr.length > 0) {
change('rejected', reason);
return;
}
let delayTimer = setTimeout(_ => {
change('rejected', reason);
clearTimeout(delayTimer);
}, 0);
};
try {
executor(resolve, reject);
} catch (err) {
reject(err.message);
}
}
then(resolveFn, rejectFn) {
if (typeof resolveFn !== 'function') {
resolveFn = result => {
return result;
};
}
if (typeof rejectFn !== 'function') {
rejectFn = reason => {
return MyPromise.reject(reason);
};
}
return new MyPromise((resolve, reject) => {
this.resolveArr.push(result => {
try {
let x = resolveFn(result);
if (x instanceof MyPromise) {
x.then(resolve, reject);
return;
}
resolve(x);
} catch (err) {
reject(err.message);
}
});
this.rejectArr.push(reason => {
try {
let x = rejectFn(reason);
if (x instanceof MyPromise) {
x.then(resolve, reject);
return;
}
resolve(x);
} catch (err) {
reject(err.message);
}
});
});
}
catch (rejectFn) {
return this.then(null, rejectFn);
}
static resolve(result) {
return new MyPromise(resolve => {
resolve(result);
});
}
static reject(reason) {
return new MyPromise((_, reject) => {
reject(reason);
});
}
static all(arr) {
return new MyPromise((resolve, reject) => {
let index = 0,
results = [];
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (!(item instanceof MyPromise)) continue;
item.then(result => {
index++;
results[i] = result;
if (index === arr.length) {
resolve(results);
}
}).catch(
reason => {
reject(reason);
});
}
});
}
}