现在的位置: 首页 > 综合 > 正文

Js整理备忘(08)——原型(prototype)

2012年05月11日 ⁄ 综合 ⁄ 共 2261字 ⁄ 字号 评论关闭

1、原型(prototype)是什么?与构造函数和对象有什么关系?

Js中对象的prototype属性,是该对象的构造函数的原型的引用。

图示说明:

prototype

——理解原型、构造函数(类)、对象的关系

《Javascript王者归来》一书中打了个很贴切的比方,习语有“照猫画虎”,可以理解为“照着‘某只猫’画出一类虎”,那么由这类虎构造的具体的‘某只虎’也就继承了这只猫的所有属性。这里的“某只猫”就是原型,而“虎”就是类型(构造函数)。那么具体的“某只虎”就是构造函数“虎”的一个对象实例。 

用Js代码表示就是:“虎.prototype=某只猫”或“虎.prototype=new 猫()”、“某只虎=new 虎()”、“某只虎.prototype=某只猫”。

概念化:

  • 所有的构造函数都有一个prototype属性。当函数被定义的时候,prototype属性自动创建和初始化,初始化值是一个对象。这个原型对象只带有一个属性constructor,它指回到和原型相关联的那个构造函数(这也就是每个对象都有一个constructor属性的原因)。
  • 添加给这个原型的任何一个属性,都会成为对应构造函数创建的对象的属性。即对象从它的原型那里继承属性

 

2、prototype的特性

  • 原型模式(prototype pattern)要求 一个类型(这里指构造函数)一个时刻只能有一个原型。
  • 这个类型(构造函数)的所有实例(对象),必须满足原型关系的类型链。

—— 一个例子:

<script type="text/javascript" language="javascript">
    function ClassA() { } //默认时ClassA.prototype=new Object();
    var ObjectA = new ClassA();
    
    function ClassB() { this.b = "hello"; }
    ClassB.prototype = ObjectA;  //ClassB以ClassA的对象为原型        
    var ObjectB = new ClassB();

    function ClassC() { this.c = "c"; }
    ClassC.prototype = ObjectB;  //ClassC以ClassB的对象为原型
    var ObjectC = new ClassC();
    alert(ObjectC instanceof ClassC);//true
    alert(ObjectC instanceof ClassB);//true
    alert(ObjectC instanceof ClassA);//true
    alert(ObjectC instanceof Object);//true
</script>

上面例子中的关系可用下图表示(略去内部的constructor和prototype属性的表示):

prototype2

 

3、prototype的使用

(1)给类的原型对象添加或删除属性。

—— 这一操作将直接影响相应的类(构造函数)创建的所有对象。

例:

<script language="javascript" type="text/javascript">
    function print(msg) {
        document.write(msg + "<br/>");
    }
    function Point(x, y) {
        this.x = x;
        this.y = y;
    }
    var p1 = new Point(1, 2);
    var p2 = new Point(3, 4);
    Point.prototype.z = 0;  //给Point函数的原型添加z属性,赋初值0
    print(p1.z);//输出0
    print(p2.z);//输出0
</script>

(2)使用prototype创建大量副本

—— 一般情况下,用prototype创建复杂对象的大量副本比其他方式来copy对象要快得多。

  • 以一个对象为原型,创建大量新的对象,正是原型模式(prototype pattern)的本质。
<script language="javascript" type="text/javascript">
    ……
    var p1 = new Point(1, 2);
    var points = []; //定义一个数组
    function PointPrototype() { } //定义一个空函数PointPrototype
    PointPrototype.prototype = p1; //将PointPrototype的原型设置为对象p1
    for (var i = 0; i < 10000; i++) {
        points[i] = new PointPrototype();
        //因为PointPrototype的构造函数是空函数,所有它比直接构造p1的副本快得多。
    }    
</script>

 

(3)用prototype定义静态方法

—— 习惯上,将采用prototype定义的属性和方法称为“静态属性”和“静态方法”(或称为“原型属性”和“原型方法”)。将this定义的属性和方法称为“公有属性”和“公有方法”。

<script language="javascript" type="text/javascript">
    function Point(x, y) {
        this.x = x;
        this.y = y;
    }
    Point.prototype.distance = function() {
        return Math.sqrt(this.x * this.x + this.y * this.y);
    }//用prototype避免每次调用构造函数时对this.distance的赋值操作。    
</script>

 

注意:尽量采用prototype定义对象方法,除非该方法需要创建闭包。

 

 

 

抱歉!评论已关闭.