JavaScript面向对象程序设计三——原型模式(上)
2011-12-19 23:34
429 查看
在javaScript面向对象设计一和Javascript面向对象设计二中分别介绍了工厂模式和构造函数模式,以及他们格式的优缺点,今天继续讲解原型模式。
我们创建的每一个函数都有一个prototype(原型)属性,该属性是一个对象,包含可以有特定类型的所有实例共享的属性和方法。使用它的好处就在于可以让所有对象实例共享它所包含的属性和方法,也就是说,不必在构造函数中定义对象的信息,而是可以将这些信息,直接添加在原型对象中,如下所示,还是接着改写前两篇日志中的例子:
与构造函数模式不同的是,新对象的这些属性和方法是由所有实例共享的。
以上即是原型模式的一个引子,要理解原型模式的工作原理,就需要了解ECMASCRIPT中原型的性质。
理解原型
在Javascript中,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性。在默认的情况下,虽有prototype属性都会自动获得一个constructor属性,这个属性包含一个指向prototype属性所在函数的指针,而通过这个构造函数,我们还可以继续为原型添加其他属性和方法。
创建了自定义的构造函数之后,其原型属性默认只会取得constructor属性,而至于其他的方法,则都是从Object继承来的。当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型属性。要注意的是这个连接存在于实例和构造函数原型属性之间,而不是存在于实例与构造函数之间。
在某些实现中,无法访问到内部属性(_proto_属性),但是在所有实现中都可以通过isPrototypeOf方法来确定对象之间是否存在这种原型关系。从本质上来看,如果对象的_proto_属性指向isPrototypeOf,这个方法就返回true。如下所示:
每当代码读取某个对象的某个属性时,都会执行搜索,目标是具有给定名字的属性。搜索最先从对象实例本身开始。如果在实例中找到具有给定名字的属性,则然后该属性的值,如果没有找到,则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性。如果在原型对象中找到这个属性,则返回该属性的值。这也正是对个对象实例共享原型所保存的属性和方法的基本原理。
前面说过,原型最初只包含constructor属性,而该属性也是共享的,因此可以通过对象实例访问
虽然可以通过对象实例访问保存在原型中的值,但是不能通过对象实例重写原型中的值,如果我们在实例中添加一个属性,而该属性与实例原型中的一个属性名称相同,name在实例中创建的属性会屏蔽(.net成为隐藏)原型中的那个属性,如下所示:
其中employee1.Name的Jim来自原型,二employee2.Name的sun来自实例。
当为对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性,但不会修改。使用delete则可以完全删除实例属性,从而可以让我们能够重新访问原型中属性。
我们创建的每一个函数都有一个prototype(原型)属性,该属性是一个对象,包含可以有特定类型的所有实例共享的属性和方法。使用它的好处就在于可以让所有对象实例共享它所包含的属性和方法,也就是说,不必在构造函数中定义对象的信息,而是可以将这些信息,直接添加在原型对象中,如下所示,还是接着改写前两篇日志中的例子:
function Employee() { }; Employee.prototype.Name = "Jim"; Employee.prototype.Age = 28; Employee.prototype.Job = "SoftWare Engineer"; Employee.prototype.SayName = function () { alert(this.Name); }; var employee1 = new Employee(); employee1.SayName();//Jim var emplayee2 = new Employee(); emplayee2.SayName(); //Jim alert(employee1.SayName = emplayee2.SayName);//true
与构造函数模式不同的是,新对象的这些属性和方法是由所有实例共享的。
以上即是原型模式的一个引子,要理解原型模式的工作原理,就需要了解ECMASCRIPT中原型的性质。
理解原型
在Javascript中,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性。在默认的情况下,虽有prototype属性都会自动获得一个constructor属性,这个属性包含一个指向prototype属性所在函数的指针,而通过这个构造函数,我们还可以继续为原型添加其他属性和方法。
创建了自定义的构造函数之后,其原型属性默认只会取得constructor属性,而至于其他的方法,则都是从Object继承来的。当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型属性。要注意的是这个连接存在于实例和构造函数原型属性之间,而不是存在于实例与构造函数之间。
在某些实现中,无法访问到内部属性(_proto_属性),但是在所有实现中都可以通过isPrototypeOf方法来确定对象之间是否存在这种原型关系。从本质上来看,如果对象的_proto_属性指向isPrototypeOf,这个方法就返回true。如下所示:
alert(Employee.prototype.isPrototypeOf(employee1)); //true alert(Employee.prototype.isPrototypeOf(employee2));//true
每当代码读取某个对象的某个属性时,都会执行搜索,目标是具有给定名字的属性。搜索最先从对象实例本身开始。如果在实例中找到具有给定名字的属性,则然后该属性的值,如果没有找到,则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性。如果在原型对象中找到这个属性,则返回该属性的值。这也正是对个对象实例共享原型所保存的属性和方法的基本原理。
前面说过,原型最初只包含constructor属性,而该属性也是共享的,因此可以通过对象实例访问
虽然可以通过对象实例访问保存在原型中的值,但是不能通过对象实例重写原型中的值,如果我们在实例中添加一个属性,而该属性与实例原型中的一个属性名称相同,name在实例中创建的属性会屏蔽(.net成为隐藏)原型中的那个属性,如下所示:
function Employee() { }; Employee.prototype.Name = "Jim"; Employee.prototype.Age = 28; Employee.prototype.Job = "SoftWare Engineer"; Employee.prototype.SayName = function () { alert(this.Name); }; emplayee2.Name = "Sun"; alert(employee1.Name); //Jim alert(employee2.Name);//Sun
其中employee1.Name的Jim来自原型,二employee2.Name的sun来自实例。
当为对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性,但不会修改。使用delete则可以完全删除实例属性,从而可以让我们能够重新访问原型中属性。
相关文章推荐
- JavaScript面向对象程序设计三 原型模式(上)
- Javascript高级程序设计——14.面向对象与原型(2)
- 一步步学习javascript基础篇(4):面向对象设计之创建对象(工厂、原型和构造函数等模式)
- Javascript高级程序设计——14.面向对象与原型(1 )
- JavaScript之面向对象学习七(动态原型模式、寄生构造函数模式、稳妥构造函数模式创建自定义类型)
- 原型模式——javascript的面向对象
- Javascript高级程序设计——14.面向对象与原型(3)
- 面向对象的程序设计-原型模式
- JavaScript之常见设计模式(1)(面向对象的程序设计)
- JavaScript之常见设计模式(2)(面向对象的程序设计)
- JavaScript高级程序设计之面向对象的程序设计之创建对象之组合使用构造函数模式和原型模式 第6.2.4讲笔记
- 第6章 面向对象的程序设计 6.2 原型模式
- javascript面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)
- 23_面向对象程序设计(原型【六】原型对象的常用开发模式
- 面向对象的程序设计-原型模式
- 面向对象的程序设计-原型模式(案例:下拉菜单)
- JavaScript之面向对象学习六原型模式创建对象的问题,组合使用构造函数模式和原型模式创建对象
- JavaScript高级程序设计之面向对象的程序设计之创建对象之原型模式 第6.2.3讲笔记
- javascript 面向对象全新理练之原型继承