1

本篇文章主要讲JavaScript对象中的原型模式:

1、理解原型对象

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

如下一段代码:

function Person(){

    }

    Person.prototype.name="Jessica";
    Person.prototype.age=25;
    Person.prototype.job="Web software Engineer";
    Person.prototype.sayName=function(){
        alert(this.name);
    }
    var person1=new Person();
    person1.sayName();  //"Jessiva"

    var person2=new Person();
    person2.sayName();   //"Jessiva"

    alert(person1.sayName==person2.sayName); //true

下图展示了这段代码的各个对象之间关系:

图片描述

虽然在所有的实现中都无法访问到[[prototype]],但可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系。从本质上讲,如果[[prototype]]指向调用isPrototypeOf()方法的对象(Person.prototype),那么这个方法就返回true,如下所示:

alert(Person.prototype.isPrototypeOf(person1));  //true
alert(Person.prototype.isPrototypeOf(person2));  //true

在ECMAScript5增加了一个新方法,叫object.getPrototypeOf(),在所有支持的实现中,这个方法返回[[prototype]]的值。例如:

alert(Object.getPrototypeOf(person1)==Person.prototype); //true
alert(Object.getPrototypeOf(person1).name);  //"Jessica"

使用Object.getPrototypeOf()可以方便的取得一个对象的原型,而这在利用原型实现继承(稍后会有文章更新)的情况下是非常重要的。

虽然可以通过对象实例访问保存在原型中的值,但却不恩能够通过对象实例重写原型中的值,如果我们再实例中添加了一个属性,而该属性与实例原型中的一个属性同名,那我们就在实例中创建该属性,该属性将会屏蔽原型中的那个属性。来看下面的例子:

function Person(){

    }

    Person.prototype.name="Jessica";
    Person.prototype.age=25;
    Person.prototype.job="Web software Engineer";
    Person.prototype.sayName=function(){
        alert(this.name);
    }
    var person1=new Person();
    var person2=new Person();
    
    person1.name="Greg";
    alert(person1.name); //"Greg"--来自实例
    alert(person2.name); //"Jessica"--来自原型

使用delete操作符则可以完全删除实例属性,从而让我们能够重新访问原型中的属性。

使用hasOwnProperty()方法则可以检测一个属性是存在于实例中还是存在于原型中。这个方法(继承于Object)只在给定属性存在于对象实例中,才会返回true。


mengera88
1.4k 声望66 粉丝

欢迎和我一起讨论前端方面的知识