一篇就够-JS的new实现

new的作用

function Fruit(name){
    this.name = name;
}
Fruit.prototype.show = function(){
    console.log(this.name);
}

var banana = new Fruit('banana');
//输出Fruit.protoype
console.log(Object.getPrototypeOf(banana));
//输出Fruit.prototype
console.log(banana.__proto__);
//输出'banana'
console.log(banana.show());
//输出'banana'
console.log(banana.name);
//输出true
console.log(banana.hasOwnProperty("name"));
//输出false
console.log(banana.hasOwnProperty("show"));

可以看到,经过new之后返回了一个对象,该对象的构造函数原型为Fruit.prototype,也就是proto指向Fruit.prototype
并且banana可以调用show和name属性,但name是其拥有的属性,show是原型上的属性。
也就是new做了以下几件事

  • 返回一个对象,该对象的proto指向构造函数的原型
  • 该对象会实现构造函数中的实例属性,也就是调用构造函数的apply方法

初步实现new操作符

function objectFactory(paramConstrutor){
    if(typeof paramConstrutor !== 'function' ){
        throw new Error("");
    }
    var args = Array.prototype.slice.call(arguments,1);
    //设置obj的proto为constructor的proto,也就是继承共享属性
    //两种方式,
    //一种是直接设置__proto__,官方不建议,后面可能变成只读属性
    var obj = new Object();
    obj.__proto__ = paramConstrutor.prototype;
    //一种是通过Object.create()或者该方式的polyfill
    //模拟Object.create()
    function Empty(){};
    Empty.prototype = paramConstructor.prototype;
    var obj = new Empty();
    //继承实例属性
    paramConstructor.apply(obj,args);
    return obj;
}

如果构造函数由返回值,那应该是返回新建的对象还是返回值呢?

  • 直接返回返回值,当返回值是Object、Function、Array、Date、RegExg、Error
  • 返回新建对象,当返回值是Null、Undefined、Number、Boolean、String、Symbol
function Fruit(name){
    this.name = name;
    return {
        a:1
    }
}

var banana = new Fruit('banana');
//{a:1}
console.log(banana);
function Fruit(name){
    this.name = name;
    return 1;
}

var banana = new Fruit('banana');
//Fruit {name:'banana‘}
console.log(banana);

完整代码

根据上面的返回值,进一步完善代码。
需要了解的:

  • typeof检测除了Function之外的都为object
  • typeof检测Null为object
function objectFactory(paramConstructor){
    if(typeof paramConstructor !== 'function'){
        throw new Error("");
    }
    var args = Array.prototype.slice.call(arguments,1);
    //继承共享属性,修改proto属性
    function Empty(){};
    Empty.prototype = paramConstructor.prototype;
    var obj = new Empty();
    //继承实例属性
    var result = paramConstructor.apply(obj,args);
    var isObejct = typeof result === 'object' && result !== null;
    var isFunction = typeof result === 'function';
    if(isObejct ||isFunction ){
        return result
    }
    return obj;
}

你可能感兴趣的:(一篇就够-JS的new实现)