Javascript模拟实现new原理解析
new是JS中的一个关键字,用来将构造函数实例化的一个运算符。例子:
functionAnimal(name){ this.name=name; } Animal.prototype.sayName=function(){ console.log("I'm"+this.name); } varcat=newAnimal('Tom'); console.log(cat.name);//Tom console.log(cat.__proto__===Animal.prototype);//true cat.sayName();//I'mTom
从上面的例子可以得出两点结论:
- new操作符实例化了一个对象;
- 这个对象可以访问构造函数的属性;
- 这个对象可以访问构造函数原型上的属性;
- 对象的**__proto__**属性指向了构造函数的原型;
由于new是关键字,我们只能去声明一个函数去实现new的功能,首先实现上面的三个特性,第一版代码如下:
附:对原型原型链不熟悉的可以先看理解Javascript的原型和原型链。
//construct:构造函数 functionnewFunction(){ varres={}; //排除第一个构造函数参数 varconstruct=Array.prototype.shift.call(arguments); res.__proto__=construct.prototype; //使用apply执行构造函数,将构造函数的属性挂载在res上面 construct.apply(res,arguments); returnres; }
我们测试下:
functionnewFunction(){ varres={}; varconstruct=Array.prototype.shift.call(arguments); res.__proto__=construct.prototype; construct.apply(res,arguments); returnres; } functionAnimal(name){ this.name=name; } Animal.prototype.sayName=function(){ console.log("I'm"+this.name); } varcat=newFunction(Animal,'Tom'); console.log(cat.name);//Tom console.log(cat.__proto__===Animal.prototype);//true cat.sayName();//I'mTom
一切正常。new的特性实现已经80%,但new还有一个特性:
functionAnimal(name){ this.name=name; return{ prop:'test' }; } varcat=newAnimal('Tom'); console.log(cat.prop);//test console.log(cat.name);//undefined console.log(cat.__proto__===Object.prototype);//true console.log(cat.__proto__===Animal.prototype);//false
如上,如果构造函数return了一个对象,那么new操作后返回的是构造函数return的对象。让我们来实现下这个特性,最终版代码如下:
//construct:构造函数 functionnewFunction(){ varres={}; //排除第一个构造函数参数 varconstruct=Array.prototype.shift.call(arguments); res.__proto__=construct.prototype; //使用apply执行构造函数,将构造函数的属性挂载在res上面 varconRes=construct.apply(res,arguments); //判断返回类型 returnconResinstanceofObject?conRes:res; }
测试下:
functionAnimal(name){ this.name=name; return{ prop:'test' }; } varcat=newFunction(Animal,'Tom'); console.log(cat.prop);//test console.log(cat.name);//undefined console.log(cat.__proto__===Object.prototype);//true console.log(cat.__proto__===Animal.prototype);//false
以上代码就是我们最终对new操作符的模拟实现。我们再来看下官方对new的解释
引用MDN对new运算符的定义:
new运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
new操作符会干下面这些事:
- 创建一个空的简单JavaScript对象(即{});
- 链接该对象(即设置该对象的构造函数)到另一个对象;
- 将步骤1新创建的对象作为this的上下文;
- 如果该函数没有返回对象,则返回this。
4条都已经实现。还有一个更好的实现,就是通过Object.create去创建一个空的对象:
//construct:构造函数 functionnewFunction(){ //通过Object.create创建一个空对象; varres=Object.create(null); //排除第一个构造函数参数 varconstruct=Array.prototype.shift.call(arguments); res.__proto__=construct.prototype; //使用apply执行构造函数,将构造函数的属性挂载在res上面 varconRes=construct.apply(res,arguments); //判断返回类型 returnconResinstanceofObject?conRes:res; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。