{T}

高质量代码

高质量代码的特点

  • 规范性:符合代码规范,逻辑清晰可读
  • 完整性:考虑全面所有功能
  • 鲁棒性:处理异常输入和边界情况

手写 new

ES6 使用 class 代替了 ES5 的构造函数

javascript
class Foo {
  constructor(name) {
    this.name = name
    this.city = '北京'
  }
  getName() {
    return this.name
  }
}

const f = new Foo('小叶')

其实 class 就是一个语法糖,它本质上和构造函数是一样的

javascript
function Foo(name) {
  this.name = name
  this.city = '北京'
}
Foo.prototype.getName = function () { // 注意,这里不可以用箭头函数
  return this.name
}
const f = new Foo('小叶')

new 对象的过程

  • 创建一个空对象 obj,继承构造函数的原型
  • 执行构造函数(将 obj 作为 this)
  • 返回 obj

代码参考 new.ts

typescript
export function customNew<T>(constructor: Function, ...args: any[]): T {
  // 1. 创建一个空对象,继承 constructor 的原型
  const obj = Object.create(constructor.prototype)
  // 2. 将 obj 作为 this ,执行 constructor ,传入参数
  constructor.apply(obj, args)
  // 3. 返回 obj
  return obj
}

class Foo {
  name: string
  city: string
  n: number

  constructor(name: string, n: number) {
    this.name = name
    this.city = '南京'
    this.n = n
  }

  getName() {
    return this.name
  }
}

// const f = new Foo('小叶', 100)
const f = customNew<Foo>(Foo, '小叶', 100)
console.info(f)
console.info(f.getName())

运行单元测试:npx jest src/03-write-code/new.test.ts

typescript
import {customNew} from './new'

describe('自定义 new', () => {
    it('new', () => {
        class Foo {
            name: string
            city: string
            n: number

            constructor(name: string, n: number) {
                this.name = name
                this.city = '南京'
                this.n = n
            }
            getName() {
                return this.name
            }
        }

        const f = customNew<Foo>(Foo, '小叶', 100)
        expect(f.name).toBe('小叶')
        expect(f.city).toBe('南京')
        expect(f.n).toBe(100)
        expect(f.getName()).toBe('小叶')
    })
})

Object.create 和 {} 的区别

  • Object.create 可以指定原型,创建一个空对象
  • {} 就相当于 Object.create(Object.prototype) ,即 Object 原型的空对象