前端工程师-我这样理解new

上篇回顾

prototype与constructor都是为了实现js继承时对不同问题的解决方案

prototype:解决实例对构造函数的方法与变量的继承问题

constructor:说明实例与构造函数的关系

这一节我们来看看new的过程

new操作符后的结果

在上一节,我们反复出现了这样的代码

 

 附上代码:

function ObjectDemo(){
  this.abc = {};  
}
ObjectDemo.prototype.a ='123';
ObjectDemo.prototype.b ='234';
var obj = new ObjectDemo();

console.log("ObjectDemo.constructor:"+ObjectDemo.constructor);
console.log("ObjectDemo.prototype.constructor:"+ObjectDemo.prototype.constructor);
console.log("obj.constructor:"+obj.constructor);// 输出ObjectDemo.constructor:function Function() { [native code] }ObjectDemo.prototype.constructor:function ObjectDemo(){ this.abc = {};} obj.constructor:function ObjectDemo(){this.abc = {};}

var obj = new ObjectDemo(); 我们总是在new一个实例去举例子,说明问题,同时上篇我们还提到这样两句话


现在就来说明这两句话的问题

1.为什么实例一旦创建,我们的prototype就引用好了?
2.为什么new之后返回还是个对象?

这两个问题最终还是归咎于new操作到底做了什么事情

其实大家去度娘那里搜,有非常多优秀的文章都讲了new操作符到底做了什么事情,我之所以再写一篇其实是为了和之前的文章串起来去理解new,为了给自己讲清楚的同时,希望也能为伙伴们提供到一点点帮助,帮助大家记忆。

那我们就自己来写一个new函数试试看。

这里一定要明白一个点,我们的new函数 是需要接收一个构造函数为参数的,还记得js的new操作怎么写的吗 var obj = new ObjectDemo(); 我们是在新建ObjectDemo构造函数的实例的,所以我们一定要接收一个构造函数为参数

function newObjFun(obj){
    // 之前文章说过,new运算之后还是返回一个实例对象,那我们就首先建一个对象
    var tempObject ={};
    // 自动引用好的prototype 
    // todo ?
    //最终我们要返回这个对象
    return tempOject;
}

基本框架就出来了:

现在来看这里我们如何解决原型引用这一步呢,上一篇中,我们经过实验发现,其实实例的原型,与构造函数的原型是相同的:看下方的截图,所以我们才可以直接修改实例的原型,然后构造函数的原型也就被影响到了,大家看,我用的是“全等”的符号进行判断的

 那么这样就好办了,我们的代码可以这样完善,大家看到浏览器控制台的友好提示了吗? ^_______^

 附上代码:

function newObjFun(obj){
    // 之前文章说过,new运算之后还是返回一个对象,那我们就首先建一个对象
    var tempObject ={};
    // 自动引用好的prototype 
    // tempObject._proto_ = obj.prototype; 目前已经不赞成直接使用_proto_属性去修改原型了,因此我们使用Object.setPrototypeOf()方法
     Object.setPrototypeOf(tempObject._proto_, obj.prototype); //最终我们要返回这个对象 return tempOject; }

感觉我们的函数应该可以用了吧,来我们试试:这里我要写两个函数,来对比我们自己写的new方法与js的new操作符后的结果

 附上代码:

function newObjFun(objTemp){
    // 之前文章说过,new运算之后还是返回一个对象,那我们就首先建一个对象
    var tempObject ={};
    // 自动引用好的prototype
    // tempObject._proto_ = objTemp.prototype; 目前已经不赞成直接使用_proto_属性去修改原型了,因此我们使用Object.setPrototypeOf()方法
     Object.setPrototypeOf(tempObject, objTemp.prototype);
    //最终我们要返回这个对象
    return tempObject;
}

//这是我们的构造函数
function CreateFunc(){
    this.a = "123";
}
CreateFunc.prototype.hello = "hi i am a function"


var obj = new CreateFunc();

//这是js的new操作的结果
console.log("-----------js的new操作结果-----------");
console.log("obj._proto_:");
console.log(Object.getPrototypeOf(obj));
console.log("CreateFunc.prototype:");
console.log(CreateFunc.prototype);
console.log("obj.constructor:");
console.log(obj.constructor);
console.log("obj.hello:");
console.log(obj.hello);
console.log("------------------------------------");

var custom = newObjFun(CreateFunc);
//这是js的new操作的结果
console.log("-----------自定义new操作结果-----------");
console.log("custom._proto_:");
console.log(Object.getPrototypeOf(custom));
console.log("CreateFunc.prototype:");
console.log(CreateFunc.prototype);
console.log("custom.constructor:");
console.log(custom.constructor);
console.log("custom.hello:");
console.log(custom.hello);
console.log("------------------------------------");

执行结果,大家发现我们竟然就成功了,跟new的操作是一模一样,我们custom 与 obj都是一个父亲,同时引用方法也是正确的

 看似我们好像成功了,接下来我们再看看new出来的对象一致不一致呢?

function newObjFun(objTemp){
    // 之前文章说过,new运算之后还是返回一个对象,那我们就首先建一个对象
    var tempObject ={};
    // 自动引用好的prototype
    // tempObject._proto_ = objTemp.prototype; 目前已经不赞成直接使用_proto_属性去修改原型了,因此我们使用Object.setPrototypeOf()方法
     Object.setPrototypeOf(tempObject, objTemp.prototype);
    //最终我们要返回这个对象
    return tempObject;
}

//这是我们的构造函数
function CreateFunc(){
    this.a = "123";
}
CreateFunc.prototype.hello = "hi i am a function"


var obj = new CreateFunc();
console.log(obj);

var custom = newObjFun(CreateFunc);
console.log(custom);

执行结果

 

 相信大家已经看到了结果,珍贵的变量a丢了,怎么办,怎么才能把a放到我的新对象中呢?我想到了阮老师说的,构造函数的绑定,此时我们再来修改代码

 

 

function newObjFun(objTemp){
    // 之前文章说过,new运算之后还是返回一个对象,那我们就首先建一个对象
    var tempObject ={};
    // 自动引用好的prototype
    // tempObject._proto_ = objTemp.prototype; 目前已经不赞成直接使用_proto_属性去修改原型了,因此我们使用Object.setPrototypeOf()方法
     Object.setPrototypeOf(tempObject, objTemp.prototype);
     // 将父对象的构造函数绑定在子对象上
    objTemp.apply(tempObject, arguments);
    //最终我们要返回这个对象
    return tempObject;
}

//这是我们的构造函数
function CreateFunc(){
    this.a = "123";
}
CreateFunc.prototype.hello = "hi i am a function"


var obj = new CreateFunc();
console.log(obj);

var custom = newObjFun(CreateFunc);
console.log(custom);

运行结果,看出来了,我们成功了,我们让tempObject 指向了CreateFunc这个构造函数,同时,我们也继承了CreateFunc的原型

 

  至此,完结

 

 

 

posted @ 2021-03-28 18:14  ELSE-IF  阅读(70)  评论(0)    收藏  举报