site infoHacknerd | Tech Blog
blog cover

🏈 [手写代码] EcmaScript API

JavaScript

call/apply/bind

typescriptCopy
/**
 * 手写call
 */
(Function.prototype as any).myCall = function (context: any, ...rest: any[]) {
  const fn = this // this指向 Person.prototype.say
  const symbol = Symbol(this)
  context[symbol] = fn // 将fn绑定到context对象下,此时say的this会指向context
  context[symbol](...rest)
  delete context[symbol]
}

class Person {
  // 年龄
  public age = 18

  constructor(age: number) {
    this.age = age
  }

  // 方法
  public say(): void {
    console.log(this.age);
  };
}

const person1 = new Person(1)
const person2 = new Person(2);

(person1.say as any).myCall(person2) // 2

sleep/delay

typescriptCopy
const sleep = (seconds: number) => new Promise((resolve) => setTimeout(resolve, seconds))

const delay = (fun: Function, seconds: number, ...args: any[]) => new Promise((resolve) => setTimeout(() => {
  fun(...args)
  resolve(1)
}, seconds))

console.log('run');

sleep(3000).then(() => {
  console.log('finished sleep');
})

delay((data: number) => { console.log(data) }, 3000, 10).then(() => {
  console.log('finished delay');
})

// 输出
// run
// finished sleep
// 10
// finished delay

Promise.all

typescriptCopy
// 继发版本
(Promise.prototype as any).myAll = async function (values: any[]): Promise<any[]> {
  const result = []
  for (let index = 0; index < values.length; index++) {
	  // 异步出错等同于被Promise rejct

    result.push(await values[index]) 
  }
  
  return result
}

// 并发版本
(Promise.prototype as any).myAll = async function (values: any[]): Promise<any[]> {

	const result: any[] = []

  const p = values.map(async (ele, index) => {
    result.push(await ele)
  })

  for (const iterator of p) {
    await iterator
  }
  return result
 }


const promise1 = new Promise((resolve) => setTimeout(() => {
  resolve("promise1")
  console.log("promise1");
}, 1000))
const promise2 = new Promise((resolve, reject) => setTimeout(() => {
  reject("promise2")
  console.log("promise2");
}, 2000));

(Promise.prototype as any).myAll([promise1, promise2]).then((data: any) => {
  console.log({ ...data });
}).catch((err: any) => {
  console.log('err', err);
})

// 输出
// promise1
// promise2
// err promise2

isArray

typescriptCopy
(Array.prototype as any).myIsArray = function (obj: any) {
  // return typeof obj === 'object' && obj instanceof Array
  return Object.prototype.toString.call(obj) === '[object Array]'
}

flat

typescriptCopy
function flat(data: any[], dept: number = 0): any[] {

  if (dept === 0) return data
  return data.reduce((pre: any[], current) => {
    // let a = [0]
    // a.concat([1,2,3]) -> [0 ,1, 2, 3]
    return pre.concat(Array.isArray(current) ? flat(current, dept - 1) : current)
  }, [])
}

console.log(flat([1, 2, [3, 4], 1], 1));


trim

typescriptCopy
(String.prototype as any).myTrim = function () {
  const str = this;
  return str.replace(/^\s+|\s+$/g, '')
};

console.log(('   23    ' as any).myTrim());

Contents

  • call/apply/bind
  • sleep/delay
  • Promise.all
  • isArray
  • flat
  • trim

2024/04/10 08:45