忘记你已经学到的关于原型属性的一切,它可能就是你对原型困惑的根源所在。一个对象的真正原型是被对象内部的[[Prototype]]属性(property)所持有。ECMA引入了标准对象原型访问器Object.getPrototype(object),到目前为止只有Firefox和chrome实现了此访问器。除了IE,其他的浏览器支持非标准的访问器__proto__,如果这两者都不起作用的,我们需要从对象的构造函数中找到的它原型属性。下面的代码展示了获取对象原型的方法 var a = {};
如果仅仅只是因为一个实例而使用原型是没有多大意义的,这和直接添加属性到这个实例是一样的,假如我们已经创建了一个实例对象 ,我们想要继承一个已经存在的对象的功能比如说Array,我们可以像下面这样做( 在支持__proto__ 的浏览器中) //unusual case and does not work in IE var a = {}; a.__proto__ = Array.prototype; a.length; //0 ———————————————————————————————————– 译者注:上面这个例子中,首先创建了一个对象a,然后通过a的原型来达到继承Array 这个已经存在的对象的功能 ———————————————————————————————————–
//创建一个函数b var b = function(){ var one; } //使用b创建一个对象实例c var c = new b(); //查看b 和c的构造函数 b.constructor; // function Function() { [native code]} b.constructor==Function.constructor; //true c.constructor; //实例c的构造函数 即b function(){ var one; } c.constructor==b //true //b是一个函数,查看b的原型如下 b.constructor.prototype // function (){} b.__proto__ //function (){}
//Constructor. <em>this</em> is returned as new object and its internal [[prototype]] property will be set to the constructor's default prototype property var Circle = function (radius) { this .radius = radius; //next line is implicit, added for illustration only //this.__proto__ = Circle.prototype; } //augment Circle's default prototype property thereby augmenting the prototype of each generated instance Circle.prototype.area = function () { return Math.PI* this .radius* this .radius; } //create two instances of a circle and make each leverage the common prototype var a = new Circle(3), b = new Circle(4); a.area().toFixed(2); //28.27 b.area().toFixed(2); //50.27 棒极了。如果我更改了构造函数的原型,是否意味着已经存在的该构造函数的实例将获得构造函数的最新版本?
var A = function (name) { this .name = name; } var a = new A( 'alpha' ); a.name; //'alpha' A.prototype.x = 23; a.x; //23 —————————————————————————————————— 译者注:这个和上例中的一样,实例对象a的原型(a.__proto__)是对函数A的原型属性(A.prototype)的引用,所以如果修改的是A的原型属性,
var A = function (name) { this .name = name; } var a = new A( 'alpha' ); a.name; //'alpha' A.prototype = {x:23}; a.x; //null —————————————————————————————————————— 译者注:即如果在实例被创建之后,改变了函数的原型属性所指向的对象,也就是改变了创建实例时实例原型所指向的对象
var A = function () {}; A.prototype.constructor == A; //true var a = new A(); a.constructor == A; //true (a's constructor property inherited from it's prototype) instance of 和原型有什么关系
如果a的原型属于A的原型链,表达式a instance of A 值为true。这意味着 我们可以对instance of 耍个诡计让它不在起作用 var A = function () {}
var a = new A();
a.__proto__ == A.prototype; //true - so instanceof A will return true
a instanceof A; //true;
//mess around with a's prototype
a.__proto__ = Function.prototype;
//a's prototype no longer in same prototype chain as A's prototype property
a instanceof A; //false 还能使用原型做些什么呢?
记住我曾经所提到过的每个构造函数都有一个原型属性,它用来为每一个它所创建的实例提供原型。这同样也适用原生态的构造函数Function,String等,扩展这个属性,我们可以达到扩展指定构造函数的所有实例 我曾经在之前的很多文章中使用过这个技巧来演示函数的拓展。在tracer utility 这篇文章中所有的string实例都实现了times这个方法,对字符串本身进行指定数目的复制 String.prototype.times = function (count) { return count < 1 ? '' : new Array(count + 1).join( this ); }