function deepClone (Origin, Target) {
let strCall = Object.prototype.toString.call,
strArr = '[object, Array]';
if (!Target) {
Target = strCall(Origin) === strArr ? [] : {};
}
for (let prop in Origin) {
if (Origin.hasOwnProperty(prop)) {
if (Origin[prop] !== null && strCall(Origin[prop]) === 'object') {
Target[prop] = strCall(Origin[prop]) === strArr ? [] : {};
deepClone(Origin[prop], Target[prop]);
} else {
Target[prop] = Origin[prop];
}
}
}
}
Function.prototype.myCall = function (params, ...args) {
if (typeof this !== 'function') {
throw new Error("Type error");
}
params = params || window;
params.fn = this;
let result = params.fn(...args);
delete params.fn;
return result;
};
Function.prototype.myApply = function (params, args) {
if (typeof this !== 'function') {
throw new Error("Type error");
}
params = params || window;
params.fn = this;
let result = params.fn(...args);
delete params.fn;
return result;
};
Function.prototype.myBind = function (params, ...args) {
if (typeof this !== 'function') {
throw new Error("Type error");
}
params = params || window;
let fn = this;
return function Fn () {
return fn.apply(this instanceof Fn ? this : params, args.concat(...arguments));
};
};
function myNew (content, ...args) {
const _this = new Object();
_this.__proto__ = content.prototype;
const res = content.apply(obj, args);
return typeof res === 'object' ? res : obj;
}
class myPromise {
static PENDING = 'pending';
static FULFILLED = 'fulfilled';
static REJECTED = 'rejected';
constructor(fn) {
this.result = null;
this.promiseState = myPromise.PENDING;
this.onFulfilledCallback = [];
this.onRejectedCallback = [];
try {
fn(this.resolve.bind(this), this.reject.bind(this));
} catch (e) {
this.reject(e);
}
}
resolve (value) {
if (this.promiseState === myPromise.PENDING) {
this.result = value;
this.promiseState = myPromise.FULFILLED;
this.onFulfilledCallback.forEach(cb => cb());
}
}
reject (reason) {
if (this.promiseState === myPromise.PENDING) {
this.result = reason;
this.promiseState = myPromise.REJECTED;
this.onRejectedCallback.forEach(cb => cb());
}
}
then (onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => {
throw reason;
};
let promise2 = new myPromise((resolve, reject) => {
switch (this.promiseState) {
case myPromise.FULFILLED:
setTimeout(() => {
try {
let x = onFulfilled(this.result);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
throw e;
}
});
break;
case myPromise.REJECTED:
setTimeout(() => {
try {
let x = onRejected(this.result);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
throw e;
}
});
break;
case myPromise.PENDING:
this.onFulfilledCallback.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.result);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
throw e;
}
});
});
this.onRejectedCallback.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.result);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
throw e;
}
});
});
break;
}
});
return promise2;
}
}
function resolvePromise (promise2, x, resolve, reject) {
if (x === promise2) {
return reject(new TypeError("Chaining cycle detected for promise"));
}
if (x instanceof myPromise) {
x.then(y => {
resolvePromise(promise2, y, resolve, reject);
}, reject);
} else if (x !== null && (typeof x === 'function' || typeof x === 'object')) {
let then;
try {
then = x.then;
} catch (e) {
reject(e);
}
if (typeof then === 'function') {
let called = false;
try {
then.call(x, y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, r => {
if (called) return;
called = true;
reject(r);
});
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
reject(x);
}
} else {
return resolve(x);
}
}