Skip to content

Commit c452e1c

Browse files
committed
手写代码
手写`instanceOf`或`Object.prototype.isPrototypeOf` 手写`new` 手写`Promise`
1 parent a028e46 commit c452e1c

File tree

6 files changed

+285
-92
lines changed

6 files changed

+285
-92
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
1. [JS学习笔记](./网站前端/JS学习笔记/README.md)
4040
2. [JS实用方法](./网站前端/JS方法积累/实用方法/README.md)
4141
3. [JS正则表达式](./网站前端/JS正则表达式/README.md)
42+
4. [JS手写代码](./网站前端/JS方法积累/手写代码/README.md)
4243
3. HTML+CSS
4344

4445
1. [HTML+CSS学习笔记](./网站前端/HTML+CSS学习笔记/README.md)

网站前端/JS学习笔记/README.md

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -178,60 +178,6 @@
178178
179179
1. 若Func返回**引用数据类型**,则这个引用数据类型的值赋值给newObj。
180180
2. 若Func返回基本数据类型或返回this或无返回,则obj赋值给newObj。
181-
182-
><details>
183-
><summary>模拟实现一个<code>new</code></summary>
184-
>
185-
>```javascript
186-
>// 第一个参数是构造函数,后面是参数
187-
>// 不支持class的构造函数,因为class必须`new`创建,否则报错。也不支持new.target。
188-
>function objectFactory () {
189-
> const obj = new Object()
190-
> const Constructor = Array.prototype.shift.call(arguments)
191-
> Object.setPrototypeOf(obj, Constructor.prototype)
192-
> const ret = Constructor.apply(obj, arguments)
193-
>
194-
> return (typeof ret === 'object' && ret !== null) || typeof ret === 'function' ? ret : obj
195-
>}
196-
>
197-
>/* 使用测试 */
198-
>function A (a, b) {
199-
> this.a = a
200-
> this.b = b
201-
>}
202-
>function B (a, b) {
203-
> this.a = a
204-
> this.b = b
205-
> return null
206-
>}
207-
>function C (a, b) {
208-
> this.a = a
209-
> this.b = b
210-
> return 1
211-
>}
212-
>function D (a, b) {
213-
> this.a = a
214-
> this.b = b
215-
> return function () {
216-
> return a + b
217-
> }
218-
>}
219-
>function E (a, b) {
220-
> this.a = a
221-
> this.b = b
222-
> return {
223-
> otherA: a,
224-
> otherB: b
225-
> }
226-
>}
227-
>
228-
>console.log(objectFactory(A, 'a1', 'b1'), new A('a1', 'b1'))
229-
>console.log(objectFactory(B, 'a1', 'b1'), new B('a1', 'b1'))
230-
>console.log(objectFactory(C, 'a1', 'b1'), new C('a1', 'b1'))
231-
>console.log(objectFactory(D, 'a1', 'b1'), new D('a1', 'b1'))
232-
>console.log(objectFactory(E, 'a1', 'b1'), new E('a1', 'b1'))
233-
>```
234-
></details>
235181
</details>
236182
6. <a name="函数-参数"></a>参数
237183

网站前端/JS方法积累/废弃代码/README.md

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232

3333
1. [`requestAnimationFrame``cancelAnimationFrame`](#原生jsrequestanimationframe和cancelanimationframe的polyfill)
3434
1. [`Date.now`](#原生jsdatenow的polyfill)
35-
1. [`Object.create`](#原生jsobjectcreate的polyfill)
3635
1. [`Array.isArray`](#原生jsarrayisarray的polyfill)
3736
1. [`Array.prototype.map`](#原生jsarrayprototypemap的polyfill)
3837
1. [`Function.prototype.bind`](#原生jsfunctionprototypebind的polyfill)
@@ -1139,41 +1138,6 @@ if (typeof Date.now !== 'function') {
11391138
```
11401139
>`Date.now()`相对于`new Date().getTime()`及其他方式,可以避免生成不必要的`Date`对象,更高效。
11411140

1142-
### *原生JS*`Object.create`的Polyfill
1143-
>来自:[MDN:Object.create](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Polyfill)。
1144-
1145-
```javascript
1146-
if (typeof Object.create !== 'function') {
1147-
Object.create = (function () {
1148-
function Temp() {}
1149-
1150-
var hasOwn = Object.prototype.hasOwnProperty;
1151-
1152-
return function (O) {
1153-
if (typeof O != 'object') {
1154-
throw TypeError('Object prototype may only be an Object or null');
1155-
}
1156-
1157-
Temp.prototype = O;
1158-
var obj = new Temp();
1159-
Temp.prototype = null; // 不要保持一个 O 的杂散引用(a stray reference)...
1160-
1161-
if (arguments.length > 1) {
1162-
var Properties = Object(arguments[1]);
1163-
1164-
for (var prop in Properties) {
1165-
if (hasOwn.call(Properties, prop)) {
1166-
obj[prop] = Properties[prop];
1167-
}
1168-
}
1169-
}
1170-
1171-
return obj;
1172-
};
1173-
})();
1174-
}
1175-
```
1176-
11771141
### *原生JS*`Array.isArray`的Polyfill
11781142
>来自:[MDN:Array.isArray](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray#Polyfill)。
11791143

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
# JS手写代码
2+
3+
## 目录
4+
1. [手写`Object.create`](#手写objectcreate)
5+
1. [手写`instanceOf``Object.prototype.isPrototypeOf`](#手写instanceof或objectprototypeisprototypeof)
6+
1. [手写`new`](#手写new)
7+
1. [手写`Promise`](#手写promise)
8+
1. [手写``](#手写)
9+
1. [手写``](#手写)
10+
1. [手写``](#手写)
11+
12+
13+
---
14+
### 手写`Object.create`
15+
```javascript
16+
function create(proto, propertiesObject) { // 不支持null
17+
function F() {}
18+
19+
F.prototype = proto;
20+
F.prototype.constructor = F;
21+
22+
const obj = new F();
23+
propertiesObject && Object.defineProperties(obj, propertiesObject);
24+
25+
return obj;
26+
}
27+
```
28+
29+
### 手写`instanceOf``Object.prototype.isPrototypeOf`
30+
```javascript
31+
function instanceOf(obj, constructor) {
32+
if (typeof obj !== "object" || obj === null) return false;
33+
34+
// 获得对象原型链(非标准:obj.__proto__)
35+
let proto = Object.getPrototypeOf(obj);
36+
37+
// 沿着原型链向上查找,直到找到构造函数的原型或到达原型链的顶部(null)
38+
while (proto) {
39+
if (proto === constructor.prototype) {
40+
return true;
41+
}
42+
proto = Object.getPrototypeOf(proto);
43+
}
44+
return false;
45+
}
46+
```
47+
48+
### 手写`new`
49+
```javascript
50+
function myNew(constructor, ...args) {
51+
// 创建:原型是传入构造函数的 空对象
52+
const obj = Object.create(constructor.prototype);
53+
54+
// 调用构造函数,并且this绑定到obj上
55+
const value = constructor.apply(obj, args);
56+
57+
// 如果构造函数有返回值,并且返回的是对象,就返回value ;否则返回obj
58+
return value instanceof Object ? value : obj;
59+
// (typeof value === 'object' && value !== null) || typeof value === 'function' 等价于 value instanceof Object
60+
}
61+
```
62+
63+
### 手写`Promise`
64+
```javascript
65+
class MyPromise {
66+
// 状态值
67+
static PENDING = "pending";
68+
static FULFILLED = "fulfilled";
69+
static REJECTED = "rejected";
70+
71+
// 状态
72+
status = MyPromise.PENDING;
73+
// 用于存储 Promise 的结果值
74+
value = null;
75+
// 用于存储 错误信息
76+
error = null;
77+
// 用于存储 成功回调函数的队列
78+
successCallbacks = [];
79+
// 用于存储 失败回调函数的队列
80+
errorCallbacks = [];
81+
// 用于存储 结束回调函数的队列
82+
endCallbacks = [];
83+
84+
constructor(executor) {
85+
const resolve = (res) => {
86+
if (this.status === MyPromise.PENDING) {
87+
this.status = MyPromise.FULFILLED;
88+
this.value = res;
89+
90+
// 处理pending时推入的回调
91+
this.successCallbacks.forEach((fn) => fn(this.value));
92+
this.endCallbacks.forEach((fn) => fn());
93+
}
94+
};
95+
const reject = (err) => {
96+
if (this.status === MyPromise.PENDING) {
97+
this.status = MyPromise.REJECTED;
98+
this.error = err;
99+
100+
// 处理pending时推入的回调
101+
this.errorCallbacks.forEach((fn) => fn(this.error));
102+
this.endCallbacks.forEach((fn) => fn());
103+
}
104+
};
105+
try {
106+
// 执行(传入 执行成功回调函数 和 执行失败回调函数 作为参数)
107+
executor(resolve, reject);
108+
} catch (e) {
109+
reject(e);
110+
}
111+
}
112+
113+
// then 方法,用于注册成功回调函数和失败回调函数
114+
then(onFulfilled, onRejected) {
115+
return new MyPromise((resolve, reject) => {
116+
// 模拟microtask
117+
setTimeout(() => {
118+
const fun = (res) => {
119+
if (res instanceof MyPromise) {
120+
res.then(resolve, reject);
121+
} else {
122+
resolve(res);
123+
}
124+
};
125+
126+
switch (this.status) {
127+
case MyPromise.FULFILLED: {
128+
try {
129+
if (typeof onFulfilled === "function") {
130+
const res = onFulfilled(this.value);
131+
fun(res);
132+
} else {
133+
resolve(this.value);
134+
}
135+
} catch (e) {
136+
reject(e);
137+
}
138+
break;
139+
}
140+
case MyPromise.REJECTED: {
141+
try {
142+
if (typeof onRejected === "function") {
143+
const res = onRejected(this.error);
144+
fun(res);
145+
} else {
146+
reject(this.error);
147+
}
148+
} catch (e) {
149+
reject(e);
150+
}
151+
break;
152+
}
153+
case MyPromise.PENDING: {
154+
this.successCallbacks.push(() => {
155+
try {
156+
if (typeof onFulfilled === "function") {
157+
const res = onFulfilled(this.value);
158+
fun(res);
159+
} else {
160+
resolve(this.value);
161+
}
162+
} catch (e) {
163+
reject(e);
164+
}
165+
});
166+
this.errorCallbacks.push(() => {
167+
try {
168+
if (typeof onRejected === "function") {
169+
const res = onRejected(this.error);
170+
fun(res);
171+
} else {
172+
reject(this.error);
173+
}
174+
} catch (e) {
175+
reject(e);
176+
}
177+
});
178+
break;
179+
}
180+
}
181+
});
182+
});
183+
}
184+
185+
// catch 方法,用于注册失败回调函数(参考then)
186+
catch(onRejected) {
187+
return this.then(null, onRejected);
188+
}
189+
190+
// finally 方法,用于注册结束回调函数
191+
finally(onReached) {
192+
return new MyPromise((resolve, reject) => {
193+
// 模拟microtask
194+
setTimeout(() => {
195+
const finallyFun = () => {
196+
this.status === MyPromise.FULFILLED && resolve(this.value);
197+
this.status === MyPromise.REJECTED && reject(this.error);
198+
};
199+
200+
const fun = (res) => {
201+
if (res instanceof MyPromise) {
202+
res.then(finallyFun, reject);
203+
} else {
204+
finallyFun();
205+
}
206+
};
207+
208+
switch (this.status) {
209+
case MyPromise.PENDING: {
210+
this.endCallbacks.push(() => {
211+
try {
212+
if (typeof onReached === "function") {
213+
const res = onReached();
214+
fun(res);
215+
} else {
216+
finallyFun();
217+
}
218+
} catch (e) {
219+
reject(e);
220+
}
221+
});
222+
break;
223+
}
224+
default: {
225+
try {
226+
if (typeof onReached === "function") {
227+
const res = onReached();
228+
fun(res);
229+
} else {
230+
finallyFun();
231+
}
232+
} catch (e) {
233+
reject(e);
234+
}
235+
break;
236+
}
237+
}
238+
});
239+
});
240+
}
241+
}
242+
```
243+
244+
### 手写``
245+
```javascript
246+
247+
```
248+
249+
### 手写``
250+
```javascript
251+
252+
```
253+
254+
### 手写``
255+
```javascript
256+
257+
```
258+
259+
### 手写``
260+
```javascript
261+
262+
```
263+
264+
### 手写``
265+
```javascript
266+
267+
```
268+
269+
### 手写``
270+
```javascript
271+
272+
```
273+
274+
### 手写``
275+
```javascript
276+
277+
```

0 commit comments

Comments
 (0)