|
| 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 | +} |
0 commit comments