2009年11月13日星期五

[note][精品]Javascript的prototype属性与new机制

<<<<<<<<<<今天看了一篇博客,把我搞得一头雾水,最后终于理解了,在这里写下自己的一些心得>>>>>>>>>>

Object的prototype属性

w3school是这么解释的:
Prototype
对该对象的对象原型的引用。对于所有的对象,它默认返回 Object 对象的一个实例。
prototype的行为类似于C++中的静态域,
将一个属性添加为prototype的属性,这个属性将被该类型创建的所有实例所共享,但是这 种共享是“只读”(无法修改属性)的。在任何一个实例中只能够用自己的同名属性覆盖这个属性,而不能够改变它。换句话说,对象在读取某个属性时,总是先检查自身域的属性表,如果有这个属性,则会返回这个属性,否则就去读取prototype域,返回protoype域上的属性。另外,JavaScript允许protoype 域引用任何类型的对象,因此,如果对protoype域的读取依然没有找到这个属性,则JavaScript将递归地查找prototype域所指向对象 的prototype域,直到这个对象的prototype域为它本身或者出现循环为止。下面的代码可以证明以上解释。

function Dog(name) {
    this.set=function(name1) {
         this.name = name1;
    }
}
Dog.prototype = {
    name:'zhou',
    shout: function() { console.log("I am " + this.name); }
};
var dog1 = new Dog();
dog1.set('xu');
dog1.shout();
Dog.prototype.shout();

运行结果为:
I am xu
I am zhou

new机制

new是Javascript的一个关键字,用于新建一个对象。如下所示:

function class() {}
var obj = new class();

那么new的内部机制是什么样的呢?new其实可以看成一个函数,代码如下:

function newObj(class, arguments) {
     var o ={};
     if (class && typeof class == 'function') {
              o.prototype = class.prototype;
              o.constructor = class;
              class.apply(o, arguments);
     }
     return o;
}

 可见new所做的事是:
  • 新建一个空对象;
  • 设置空对象的prototype与constructor;
  • 执行构造函数;
  • 返回构造完毕的对象;
例子分析:

代码如下:
function Dog(name) {
this.name = name;
Dog.prototype = {
shout: function() { alert("I am " + this.name); }
};
}
var dog1 = new Dog("Dog 1");
dog1.shout();

看上去OK,但其实有错:“Object doesn’t support this property or method”。原因可以通过new函数的内部机制知道:

     var o ={};
     if (class && typeof Dog== 'function') {
              o.prototype = Dog.prototype;
              o.constructor = Dog;
              o.name = name;
              Dog.prototype = {
                       shout: function() { alert("I am " + this.name); }
              };     
     }
     return o;
 
可以知道新建的对象根本没有shout属性。那么建立一个标准类的方法又是如何呢?

function Dog(name) {
        this.name = name;
}
Dog.prototype = {
       constructor: Dog,
       shout: function() { /* ... */ },
       run: function() { /* ... */ }
};

以上才是一个比较好的建立类的方法。把这个拆成new的机制看看如何呢?代码如下

     Dog.prototype = {
             constructor: Dog,
             shout: function() { /* ... */ },
             run: function() { /* ... */ }
     };
     var o ={};
     if (class && typeof Dog== 'function') {
              o.prototype = Dog.prototype;
              o.constructor = Dog;
              o.name = name;
     }
     return o;

因为Dog.prototype得赋值先执行了,所以这回o虽然没有新的方法,但是o.prototype有,所以同样能执行!

没有评论: