浅谈new运算的过程,从根本上搞明白创建一个对象的过程
阅读《设计模式与开发实践》对创建对象有一个深切的领悟
平时我们接触到创建一个对象大概是下面这个样子:
function Person(name){
this.name = name;
}
person.prototype.getName = function(){
return this.name;
}
var a = new Person('seve')
我平时习惯了new是一个创建对象的手段,只知道通过new加一个普通函数即可创建一个对象,但没去了解这背后的原理机制
下面就我对创建对象的认知展开阐述
调用构造函数创建对象的流程大致如下:
① 从Object.prototype上克隆一个空的对象obj;
②将构造函数赋给constructor;
③为obj指向正确的原型,即obj.__proto__ = consrtuctor.prototype
④调用construtor.apply(obj,参数)来为本来为空的对象obj设置属性
⑤结果返回obj,此时obj的原型指向构造函数的原型,继承了构造函数的原型的所有属性和方法,另外构造函数为obj对象本身设置了属性(或和方法)
<修改时间:2017.03.20>下面对第⑤步的描述进行更改:
观察下面代码,来自《设计模式与开发实践》一书:
var objectFactory = function(){
var obj = new Object(),
Constructor = [].shift.call(arguments);
obj.__proto__=Constructor.prototype;
var ret = Constructor.apply(obj,arguements);
return typeof ret ==='object'?ret:obj;
};
假设有一构造函数为A, 则var a =objectFactory(A,'seve');与var a = new A('sevn'); 效果一样 通过objectFactory函数能从机制上了解new的运算过程
所以上面第⑤步要改为:根据构造函数是否返回一个对象,返回则使用这个对象赋给a,不返回对象的话则将objectFactory的对象obj赋给a,此时obj对象是已经借用了传入的构造器来为obj设置了属性。
所以上述的a具有自己的属性 name和继承来自构造函数的原型(现在也是它自己的原型)的方法(或和属性)
总的来说:
创建一个对象实质是:从Object.prototype上克隆一个空的对象(上面第一步)+进行一些其他额外处理(上面②③④⑤步)