new 和 class 重写

142 阅读1分钟

new 和 class 重写

new 重写

Function.prototype.new = function () {
    var fn = this

    var obj = Object.create(fn.prototype)

    var res = fn.apply(obj, arguments)
    // 当构造函数返回引用值时,new 之后也需要返回该引用值
    return res instanceof Object ? res : obj
}


function Person (name) {
    this.name = name
}

Person.prototype.say = function () {
    console.log('hello world')
}

var p = Person.new('zhangsan')
console.log(p)
p.say()
var p1 = new Person('zhangsan')
console.log(p1)

function Person1 (name) {
    this.name = name
    return {
        age: 1
    }
}
var p2 = Person1.new('zhangsan')
console.log(p2)
var p3 = new Person1('zhangsan')
console.log(p3)

class重写

/**
 * 类和普通的构造函数相比有以下特点
 * 1. class 变量不能提升,存在暂时性死区(TDZ)
 * 2. class 只能通过new 进行实例化,不能像函数一样直接执行
 * 3. class 内部是采用严格模式
 * 4. class 原型上的属性不能遍历
 * 5. 在class 内部不能修改 class 的名称
 */
function MyClass (name, age) {
    "use strict"
    var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : name
    var age =  arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : age

    // 判断是否是通过new 执行 方法一
    if (typeof new.target === 'undefined') {
        throw new Error('必须通过 new 执行')
    }
    // 判断是否是通过new 执行 方法二
    // if (!(this instanceof MyClass)) {
    //   throw new Error('必须通过 new 执行')
    // }

    this.name = name
    this.age = age
}
// 定义原型上的方法以及类的静态方法
var createClass = (function () {
    function defineProperties(target, props) {
        for(var i = 0; i < props.length; i++) {
            var descriptor = props[i]
            descriptor.enumerable = descriptor.enumerable || false
            descriptor.configurable = descriptor.configurable || true

            Object.defineProperty(target, descriptor.key, descriptor)
        }
    }

    return function(constructor, protoProps, staticProps) {
        if (protoProps) defineProperties(constructor.prototype, protoProps)
        if (staticProps) defineProperties(constructor, staticProps)
    }
})()

createClass(MyClass, [
    {
        key: "say",
        value: function () {
            console.log('hello world')
        }
    },
    {
        key: 'sayHi',
        value: function () {
            console.log('Hi')
        }
    }
], [
    {
        key: "test",
        value: function () {
            console.log('static')
        }
    }
])

var p = new MyClass('zhangsan', 18)
console.log(p)
for(var value in p) {
    console.log(value) // 只会打印name和age
}
MyClass('zhangsan', 18) // 报错,必须通过new 执行