JavaScript中new创建对象原理
发布于 4 年前 作者 guiyingtan 2133 次浏览 来自 分享

原型对象概念

无论什么时候,只要创建一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针。而通过这个构造函数,可以继续为原型对象添加其他属性和方法。创建了自定义的构造函数后,其原型对象默认只会取得 constructor 属性;至于其他方法,则都从 Object 继承而来。当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。ECMA-262第5版管这个指针叫 [[Prototype]] 。脚本中没有标准的方式访问 [[Prototype]],但Firefox、Safari和Chrome在每个对象上都支持一个属性__proto__;而在其他实现中,这个属性对脚本是完全不可见的。不过,要明确的真正重要的一点就是,这个连接存在于示例和构造函数的原型对象之间,而不是存在于实例和构造函数之间。

这段话基本概述了构造函数、原型、示例之间的关系,下图表示更清晰

JavaScript中通过new创建对象,实质上是通过下面四个步骤的

1、创建一个新对象;[var o = new Object();]

2、将构造函数的作用域赋给新对象(因此this指向了这个新对象);[Person.apply(o)] [Person原来的this指向的是window]

3、执行构造函数中的代码(为这个新对象添加属性);

4、返回新对象。

可以通过如下代码还原new过程:

function Person(name,age) {
    this.name = name;
    this.age = age;
    this.sayName = function() {
        alert(this.name);
    }
}
function createPerson(name,age) {
    var o = {};
    o.name = name;
    o.age = age;
    o.sayName = function() {
        alert(this.name);
    }
    o.__proto__ = Person.prototype;
    Person.prototype.constructor = Person;
    return o;
}
function createObj(P,args) {
    var o = {};
    o.__proto__ = P.prototype;
    P.prototype.constructor = P;
    P.apply(o, args);
    return o;
}
var person1 = new Person('hth',20);
var person2 = createPerson('hth',20);
var person3 = createObj(Person,['hth',20]);

上面通过new获得的对象person1和后面直接调方法得到的person2,person3是一样的。

new总是因为建立原型继承树而存在的,如果没有new过程参与,则当

obj = new MyObjecEx()时,我们无法通过instanceof运算:obj instanceof MyObject 来了解obj在继承树上的关系。但是事实上这一过程并不需要MyObject的参与。因为instanceof只检查prototype链,并不检查函数本身。

new新对象的创建,就是不断地为this赋值而已,只不过new会为产生的对象维护<obj>.constructor属性。

回到顶部