Skip to content

Commit a1048cb

Browse files
committed
feat: add puzzle demo & supports *.csl.ts transform
1 parent 42bbc03 commit a1048cb

File tree

9 files changed

+367
-0
lines changed

9 files changed

+367
-0
lines changed

public/code/arr-func.csl.ts

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/* eslint-disable no-extend-native */
2+
3+
// 1.
4+
console.log('-------- 1. --------')
5+
Array.prototype.myMap = function map<T, R>(this: T[], callback: (value: T, index: number, array: T[]) => R, thisArg: any) {
6+
let res: R[] = []
7+
let len = this.length
8+
for (let i = 0; i < len; i++) {
9+
if (i in this) { // 处理 [empty * m, n], 避免不必要的 callback执行
10+
let value = this[i]
11+
res[i] = callback.call(thisArg, value, i, this)
12+
}
13+
}
14+
return res
15+
}
16+
{
17+
let arr = [1, 2, 3]
18+
console.log(arr.map((v, i) => ({ v, i })))
19+
let called = 0
20+
arr = new Array(10)
21+
arr[6] = 1
22+
arr[7] = 2
23+
console.log(String(arr.map((v, i) => { called++; return `${v}-${i}` })))
24+
console.log(`callback called ${called} times`)
25+
}
26+
27+
// 2.
28+
console.log('-------- 2. --------')
29+
Function.prototype.myBind = function bind(thisArg: any, ...bindArgs: any[]) {
30+
if (typeof this !== 'function') {
31+
throw new TypeError('Bind must be called on a function')
32+
}
33+
let self = this
34+
function Bound(...args) {
35+
let allArgs = [...bindArgs, ...args]
36+
let finalThis = this instanceof Bound ? this : thisArg // 处理 new F()
37+
return self.apply(finalThis, allArgs)
38+
}
39+
// -------- 1. --------
40+
// 手写bind源码
41+
// https://www.cnblogs.com/psxiao/p/11469427.html
42+
Bound.prototype = Object.create(this.prototype)
43+
// Bound.prototype.constructor = this // 这行可省略
44+
// -------- 2. --------
45+
// 前端面试之手写一个bind方法
46+
// https://blog.csdn.net/tzllxya/article/details/90702688
47+
// JavaScript中bind和new共同作用时this的指向问题
48+
// https://blog.csdn.net/qq_34629352/article/details/101384525
49+
// eslint-disable-next-line @typescript-eslint/no-empty-function
50+
// function Noop() {}
51+
// Noop.prototype = this.prototype
52+
// Bound.prototype = new Noop()
53+
// -------- end --------
54+
return Bound
55+
}
56+
{
57+
try {
58+
({}).myBind(886, 1, 2)
59+
} catch (err) {
60+
console.log(String(err))
61+
}
62+
function Foo(name) {
63+
this.name = name;
64+
}
65+
let obj = {};
66+
let Bar = Foo.myBind(obj);
67+
Bar('Jack');
68+
console.log('obj.name', obj.name); // Jack
69+
let alice = new Bar('Alice');
70+
console.log('obj.name', obj.name); // Jack
71+
console.log('alice.name', alice.name); // Alice
72+
console.log('alice instanceof Foo', alice instanceof Foo); // true
73+
console.log('alice instanceof Bar', alice instanceof Bar); // true
74+
console.log('alice.constructor === Foo', alice.constructor === Foo); // true
75+
// console.log('alice.__proto__ === Foo.prototype', alice.__proto__ === Foo.prototype); // false 没法做到true
76+
}
77+
78+
// 3.
79+
console.log('-------- 3. --------')
80+
// js手动实现new方法
81+
// https://www.jianshu.com/p/9cee6a703e01
82+
// 如何实现一个 new
83+
// https://blog.csdn.net/qq_39985511/article/details/87692673
84+
type Constructor = new (...a: any[]) => any
85+
function myNew(Ctor: Constructor, ...args: any[]) {
86+
if (typeof Ctor !== 'function') { // 处理类型判断
87+
// sometimes TypeError: (intermediate value) is not a constructor
88+
throw new TypeError(`${String(Ctor)} is not a constructor`)
89+
}
90+
// let obj = new Object()
91+
let obj = {}
92+
obj.__proto__ = Ctor.prototype
93+
let res = Ctor.apply(obj, args)
94+
return typeof res === 'object' ? res : obj
95+
}
96+
{
97+
try {
98+
myNew(886, 1, 2)
99+
} catch (err) {
100+
console.log(String(err))
101+
}
102+
function Dog(name) {
103+
this.name = name
104+
this.say = function () {
105+
console.log('dog = ' + this.name)
106+
}
107+
}
108+
function Cat(name) {
109+
this.name = name
110+
this.say = function () {
111+
console.log('cat = ' + this.name)
112+
}
113+
}
114+
let dog = myNew(Dog, 'aaa')
115+
dog.say() // 'name = aaa'
116+
console.log('dog instanceof Dog', dog instanceof Dog) // true
117+
console.log('dog instanceof Cat', dog instanceof Cat) // false
118+
let cat = myNew(Cat, 'bbb');
119+
cat.say() // 'name = bbb'
120+
console.log('cat instanceof Cat', cat instanceof Cat) // true
121+
}
122+
123+
// 4.
124+
console.log('-------- 4. --------')
125+
// 手动实现new 和 instanceof
126+
// https://www.jianshu.com/p/0f1ebd388092
127+
function myInstanceOf(obj: any, Ctor: Constructor) {
128+
if (!(Ctor instanceof Object)) { // 处理类型判断
129+
throw new TypeError('Right-hand side of \'instanceof\' is not an object')
130+
}
131+
if (typeof Ctor !== 'function') { // 处理类型判断
132+
throw new TypeError('Right-hand side of \'instanceof\' is not callable')
133+
}
134+
let p = obj == null ? null : obj.__proto__
135+
while (p) {
136+
if (p === Ctor.prototype) return true
137+
p = p.__proto__
138+
}
139+
return false
140+
}
141+
{
142+
try {
143+
myInstanceOf(0, null)
144+
} catch (err) {
145+
console.log(String(err))
146+
}
147+
try {
148+
myInstanceOf(0, {})
149+
} catch (err) {
150+
console.log(String(err))
151+
}
152+
console.log('0 of Number', myInstanceOf(0, Number))
153+
console.log('false of Number', myInstanceOf(false, Number))
154+
console.log('0 of Boolean', myInstanceOf(0, Boolean))
155+
console.log('false of Boolean', myInstanceOf(false, Boolean))
156+
console.log('false of String', myInstanceOf(0, String))
157+
console.log('\'\' of String', myInstanceOf('', String))
158+
console.log('undefined of Object', myInstanceOf(undefined, Object))
159+
console.log('null of Object', myInstanceOf(null, Object))
160+
console.log('{} of Object', myInstanceOf({}, Object))
161+
console.log('[] of Array', myInstanceOf([], Array))
162+
let dog = new Dog('aaa')
163+
console.log('dog instanceof Dog', myInstanceOf(dog, Dog)) // true
164+
console.log('dog instanceof Cat', myInstanceOf(dog, Cat)) // false
165+
let cat = new Cat('bbb');
166+
console.log('cat instanceof Cat', myInstanceOf(cat, Cat)) // true
167+
}
168+
169+
// 5.
170+
function strEnum<T extends string>(arr: Array<T>): { [K in T]: K } {
171+
let res = {} as { [K in T]: K }
172+
arr.forEach(val => {
173+
res[val] = val
174+
})
175+
return res
176+
}

public/code/arr-func.csl.ts.png

58.5 KB
Loading

public/code/async-exec-seq.csl.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// 1.
2+
console.log('---------- 1. ----------')
3+
async function async1() {
4+
console.log("async1 start");
5+
await async2();
6+
console.log("async1 end");
7+
}
8+
async function async2() {
9+
console.log("async2");
10+
}
11+
12+
console.log("script start");
13+
async1();
14+
console.log("script end");
15+
16+
// 2.
17+
await sleep(1000)
18+
console.log('---------- 2. ----------')
19+
console.log("script start");
20+
let promise1 = new Promise(function (resolve) {
21+
console.log("promise1");
22+
resolve();
23+
console.log("promise1 end");
24+
}).then(function () {
25+
console.log("promise2");
26+
});
27+
setTimeout(function () {
28+
console.log("settimeout 1");
29+
}, 2);
30+
setTimeout(function () {
31+
console.log("settimeout 2");
32+
});
33+
console.log("script end");
34+
35+
// 3.
36+
await sleep(1000)
37+
console.log('---------- 3. ----------')
38+
const dateFrom = Date.now()
39+
let i = 1;
40+
41+
const timer = setInterval(() => {
42+
console.log(i++, Date.now() - dateFrom);
43+
const s = Date.now();
44+
while (Date.now() - s < 300) {}
45+
}, 200);
46+
47+
setTimeout(() => {
48+
clearInterval(timer);
49+
}, 700);
50+
51+
// 4.
52+
await sleep(1000)
53+
console.log('---------- 4. ----------')
54+
let p = [];
55+
(function() {
56+
setTimeout(() => {
57+
console.log('timeout 0');
58+
}, 0);
59+
let i = 0;
60+
for (; i < 3; i++) {
61+
p[i] = function() {
62+
return new Promise(function(resolve) {
63+
console.log(`promise ${i}`);
64+
resolve(`promise ${i * i}`);
65+
})
66+
}
67+
}
68+
})();
69+
async function b() {
70+
console.log('async -1');
71+
}
72+
function a() {
73+
console.log(`async ${p.length}`);
74+
return async function() {
75+
console.log(`async ${p.length}`);
76+
await b();
77+
console.log('async -2')
78+
};
79+
}
80+
p.push(a());
81+
p[1]().then(console.log);
82+
p[3]();
43 KB
Loading

public/code/index.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
- nine-blocks.ts
2+
- arr-func.csl.ts
3+
- async-exec-seq.csl.ts
14
- linkedlist.tsx
25
- resume.md
36
- vditor-charts.md

public/code/nine-blocks.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// <!DOCTYPE html>
2+
// <html>
3+
// <head>
4+
// <meta charset="utf-8">
5+
// <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
6+
// <meta name="renderer" content="webkit">
7+
// <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
8+
// </head>
9+
// <body>
10+
// <!--
11+
// // 设备宽度未知,九宫格容器是一个正方形,每个宫格也是正方形,宫格边框宽度为1px
12+
// +----+----+----+
13+
// | 0A | 0B | 0C |
14+
// |----|----|----|
15+
// | 1A | 1B | 1C |
16+
// |----|----|----|
17+
// | 2A | 2B | 2C |
18+
// +----+----+----+
19+
// -->
20+
// </body>
21+
// </html>
22+
23+
appendCss(`
24+
#mountNode {
25+
padding: 20px;
26+
}
27+
.grids {
28+
display: flex;
29+
flex-wrap: wrap;
30+
justify-content: center;
31+
}
32+
.grids > div {
33+
width: 33%;
34+
border: solid 1px gray;
35+
display: flex;
36+
align-items: center;
37+
justify-content: center;
38+
margin: -1px 0 0 -1px; /* dont forget */
39+
}
40+
.grids > div:before {
41+
display: block;
42+
content: '';
43+
padding-bottom: 100%;
44+
}
45+
`)
46+
47+
let myGrids = document.createElement('div')
48+
myGrids.id = 'myGrids'
49+
myGrids.className = 'grids'
50+
51+
let arr: string[] = []
52+
for (let i = 0; i < 3; i++) {
53+
for (let j = 0; j < 3; j++) {
54+
arr.push(`${i}${String.fromCharCode(65+j)}`)
55+
}
56+
}
57+
58+
arr.forEach(val => {
59+
let div = document.createElement('div')
60+
div.textContent = val
61+
myGrids.appendChild(div)
62+
})
63+
document.querySelector('#mountNode').appendChild(myGrids)

src/playground/Playground.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
loadCss,
3737
loadJs,
3838
loadJsForceUmd,
39+
sleep,
3940
} from './util';
4041

4142
Object.assign(window, {
@@ -50,6 +51,7 @@ Object.assign(window, {
5051
Antd,
5152
React,
5253
ReactDOM,
54+
sleep,
5355
displayError,
5456
loadJsForceUmd,
5557
loadJs,

src/playground/codeTransform.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,41 @@ export let codeTransform = async (code: string, file: string) => {
88
if (isPy) return wrapPy(code);
99
if (isVue) return wrapVue(code);
1010

11+
if (/\.csl\.([tj]sx?)$/.test(file)) {
12+
file = file.replace(/(\.[tj]s)$/, '$1x');
13+
code = `
14+
let main = async (console) => {
15+
;;${code};;
16+
}
17+
let App = () => {
18+
let [logs, dispatchLogs] = useReducer((state, action) => {
19+
if (action.type === 'append') return [...state, action.content]
20+
return state
21+
}, [])
22+
useEffect(() => {
23+
let myLog = (...args) => {
24+
dispatchLogs({ type: 'append', content: JSON.stringify(args) })
25+
}
26+
let originalConsole = console
27+
let mockConsole = new Proxy(originalConsole, {
28+
get: (t, k) => {
29+
if (k === 'log') return myLog
30+
return t[k]
31+
}
32+
})
33+
main(mockConsole)
34+
}, [])
35+
return (
36+
<ul style={{ margin: '20px 0' }}>
37+
{logs.map((v, i) => {
38+
return <li key={i}>{v}</li>
39+
})}
40+
</ul>
41+
)
42+
}
43+
`;
44+
}
45+
1146
code = wrapJs(code);
1247
let hasJsx = file && ['.jsx', '.tsx'].some(ext => file.endsWith(ext));
1348
let hasTs = file && ['.ts', '.tsx'].some(ext => file.endsWith(ext));

0 commit comments

Comments
 (0)