Skip to content

Commit bb486ee

Browse files
promise-bind-reduce
1 parent 80b0529 commit bb486ee

File tree

3 files changed

+233
-0
lines changed

3 files changed

+233
-0
lines changed

js-基础/simulate/bind.js

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
Function.prototype.custom_bind = Function.prototype.custom_bind || function bind(target) {
2+
const args = Array.prototype.slice.call(arguments, 1);
3+
const self = this;
4+
5+
// 使用一个空函数, 接收当前函数的原型, 最终 new 出一个实例, 作为 bound 函数的原型, 可避免当前函数的原型污染
6+
var F = function () {};
7+
F.prototype = this.prototype;
8+
var bound = function () {
9+
var innerArgs = Array.prototype.slice.call(arguments);
10+
var finalArgs = args.concat(innerArgs);
11+
return self.apply(this.prototype && this instanceof F ? this : target || this, finalArgs);
12+
}
13+
bound.prototype = new F();
14+
return bound;
15+
}
16+
17+
const a = {
18+
b: 1,
19+
c(add) {
20+
this.b += add || 0;
21+
return this.b;
22+
}
23+
}
24+
25+
console.log(a.c());
26+
27+
const fn = a.c;
28+
console.log(fn());
29+
30+
const fnBindA = fn.custom_bind(a);
31+
console.log(fnBindA());
32+
33+
34+
const b = new fnBindA();
35+
console.log(b);
36+
37+
38+
39+

js-基础/simulate/promise.js

+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
const PENDING = 'pending';
2+
const FULFILLED = 'fulfilled';
3+
const REJECTED = 'rejected';
4+
5+
class Promise1 {
6+
// 实现一个 Promise
7+
constructor(exector) {
8+
// 存储当前状态和最终值
9+
this.state = PENDING;
10+
this.value = undefined;
11+
this.reason = undefined;
12+
13+
// 存储回调函数, 便于异步通知回调
14+
this.onFulfilledCallback = [];
15+
this.onRejectedCallback = [];
16+
this.finallyCallback = []
17+
18+
const resolve = value => {
19+
// 若状态已改变, 则不再改变
20+
if (this.state !== PENDING) return;
21+
this.value = value;
22+
this.state = FULFILLED;
23+
24+
// 异步回调通知回调函数
25+
process.nextTick(() => {
26+
this.onFulfilledCallback.forEach(fn => fn(value));
27+
this.finallyCallback.forEach(fn => fn());
28+
});
29+
}
30+
31+
const reject = reason => {
32+
if (this.state !== PENDING) return;
33+
this.reason = reason;
34+
this.state = REJECTED;
35+
36+
process.nextTick(() => {
37+
this.onRejectedCallback.forEach(fn => fn(reason));
38+
this.finallyCallback.forEach(fn => fn());
39+
});
40+
}
41+
42+
// 开始执行
43+
try {
44+
exector(resolve, reject);
45+
} catch(e) {
46+
reject(e);
47+
}
48+
}
49+
50+
// promise then 返回的并非 Promise 本身, 而是一个新的 Promise
51+
then(onFulfilled, onRejected) {
52+
onFulfilled = 'function' === typeof onFulfilled ? onFulfilled : value => value;
53+
onRejected = 'function' === typeof onRejected ? onRejected : err => {throw err};
54+
55+
// 用于递归串联 Promise, 对可能是 Promise 的函数进行尝试调用, 对返回值进行处理,
56+
function resolveRet(retPromise, ret, resove, reject) {
57+
if (ret === retPromise) return reject(new Error('retain circular'));
58+
if (ret instanceof Promise) {
59+
// 返回值本身就是 Promise, 对 Promise 进行递归调用
60+
try{
61+
ret.then(val => {
62+
resolveRet(retPromise, val, resolve, reject);
63+
});
64+
} catch(e) {
65+
reject(e);
66+
}
67+
return;
68+
}
69+
70+
// 类似 Promise
71+
if (ret && ret.then
72+
&& 'function' === typeof ret
73+
&& 'function' === typeof ret.then) {
74+
let called = false;
75+
// 尝试调用
76+
try {
77+
ret.then(val => {
78+
if (called) return;
79+
called = true;
80+
return resolveRet(retPromise, val, resolve, reject);
81+
}, err => {
82+
if (called) return;
83+
called = true;
84+
return reject(err);
85+
});
86+
} catch (e) {
87+
if (called) return;
88+
called = true;
89+
reject(e);
90+
}
91+
return;
92+
}
93+
// 其他值
94+
return resolve(ret);
95+
}
96+
97+
98+
const self = this;
99+
let retPromise = null;
100+
return retPromise = new Promise((resolve, reject) => {
101+
// 如果 self 状态已结束, 直接回调即可,
102+
if (self.state === FULFILLED) {
103+
// 此处不用 try catch 是因为在实例化 Promise 已进行了 try catch
104+
const ret = onFulfilled(self.value);
105+
// 还需对 返回值进行处理, 如: 对 Promise 进行串联, 类 Promise 进行转换, 其余类型再返回
106+
resolveRet(retPromise, ret, resolve, reject);
107+
return;
108+
}
109+
if (self.state === PENDING) {
110+
const ret = onRejected(self.reason);
111+
resolveRet(retPromise, ret, resolve, reject);
112+
return;
113+
}
114+
// 如果 self 尚未结束, 则记录至对应的回调函数
115+
self.onFulfilledCallback.push(value => {
116+
const ret = onFulfilled(val);
117+
resolveRet(retPromise, ret, resolve, reject);
118+
});
119+
self.onRejectedCallback.push(reason => {
120+
const ret = onRejected(reason);
121+
resolveRet(retPromise, ret, resolve, reject);
122+
});
123+
});
124+
}
125+
126+
catch(onRejected) {
127+
return this.then(null, onRejected);
128+
}
129+
130+
finally(onFinally) {
131+
this.then(
132+
val => Promise.resolve(onFinally()).then(() => val),
133+
reson => Promise.resolve(onFinally()).then(() => {throw reson})
134+
);
135+
}
136+
137+
static resolve(val) {
138+
return new Promise((resolve, reject) => resolve(val)) ;
139+
}
140+
static reject(reason) {
141+
return new Promise((resolve, reject) => reject(reason));
142+
}
143+
static race(pArray) {
144+
return new Promise((resolve, reject) => {
145+
pArray.forEach(p => {
146+
p.then(resolve, reject);
147+
});
148+
});
149+
}
150+
static all(pArray) {
151+
let resArray = [];
152+
let retCnt = 0;
153+
154+
return new Promise((resolve, reject) => {
155+
pArray.forEach((p, idx) => {
156+
p.then(val => {
157+
resArray[idx] = val;
158+
retCnt ++;
159+
if (retCnt === pArray.length) {
160+
resolve(resArray);
161+
}
162+
}).catch(e => {
163+
reject(e);
164+
})
165+
});
166+
});
167+
}
168+
}
169+
170+
171+
module.exports = Promise;
172+
173+
174+
175+
176+
177+
178+
179+

js-基础/simulate/reduce.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Array.prototype.custom_reduce = Array.prototype.custom_reduce || function reduce(fn, initVal) {
2+
if (!Array.isArray(this)) throw new TypeError('custom_reduce must be called by array');
3+
4+
const first = initVal === undefined ? 1 : 0;
5+
let val = initVal === undefined ? this[0] : initVal;
6+
7+
for (var i = first; i < this.length; i++) {
8+
val = fn(val, this[i]);
9+
}
10+
return val;
11+
}
12+
13+
const array = [1, 2, 3];
14+
15+
console.log(array.custom_reduce((total, cur) => total+cur, 0));

0 commit comments

Comments
 (0)