js的原型模式

  以下内容来自《JavaScript高级程序设计》第三版

  我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。

function Person(){
}
Person.prototype.name=‘lisi‘;
Person.prototype.age=23;
Person.prototype.job=‘Software engineer‘;
Person.prototype.sayName=function(){
    alert(this.name);
}
var person1 = new Person();
alert(person1.name);//lisi
var person2 = new Person();
alert(person2.name);//lisi
alert(person1.sayName==person2.sayName);//true

  1、理解原型对象

  只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性包括一个指向prototype属性所在函数的指针。就像前面例子,Person.prototype.constructor指向Person。通过这个构造函数,我们还可以继续为原型对象添加其他属性和方法。

  创建了自定义的构造函数之后,其原型对象默认只会取得constructor属性;至于其他方法,则都是从Object继承而来的。当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。

  虽然在所有访问中都无法访问[[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

  每当代码读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性。搜索首先从对象实例本身开始。如果在实例中找到具有给定名字的属性,则返回该属性的值;如果没找到,则继续搜索指针执行的原型对象,在原型对象中查找具有指定名字的属性。如果在原型对象中找到了该属性,则返回该属性的值。也就是说,当我们调用person1.sayName()方法的时候,会先后执行两次搜索。首先,会搜索实例person1的sayNane方法,没有继续搜索person1原型的sayName方法。

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

        function Person(){
        }
        Person.prototype.name=‘lisi‘;
        Person.prototype.age=23;
        Person.prototype.job=‘Software engineer‘;
        Person.prototype.sayName=function(){
            alert(this.name);
        }
        var person1 = new Person();
        alert(person1.name);//lisi
        var person2 = new Person();
        person2.name=‘zhangsan‘;
        alert(person2.name);//zhangsan

  即使将实例属性设置为null,也只会在实例中设置这个属性,而不会恢复其指向的原型的链接。不过,使用delete操作符可以完全删除实例属性,从而让我们能够重新访问原型中的属性。

        var person1 = new Person();
        alert(person1.name);//lisi
        var person2 = new Person();
        person2.name=null;
        alert(person2.name);//null
        delete person2.name;
        alert(person2.name);//lisi

  使用hasOwnProperty()方法可以检测一个属性是存在实例中还是原型中。这个方法(不要忘了是从Object继承来的)只在给定属性存在与对象实例中时返回true。

        function Person(){
        }
        Person.prototype.name=‘lisi‘;
        Person.prototype.age=23;
        Person.prototype.job=‘Software engineer‘;
        Person.prototype.sayName=function(){
            alert(this.name);
        }
        var person1 = new Person();
        alert(person1.hasOwnProperty(‘name‘));//false
        person1.name = ‘wangwu‘;
        alert(person1.name);//wangwu
        alert(person1.hasOwnProperty(‘name‘));//true

        var person2 = new Person();
        alert(person2.name);//lisi
        alert(person2.hasOwnProperty(‘name‘));//false
        delete person1.name;
        alert(person1.name);//lisi
        alert(person1.hasOwnProperty(‘name‘));//false

  2、原型与in操作符

  有两种方式使用in操作符:单独使用和在for-in中使用。在单独使用时,in操作符会在通过对象能够访问给定属性时返回true,无论该属性是存在实例中还是原型中。

        function Person(){
        }
        Person.prototype.name=‘lisi‘;
        Person.prototype.age=23;
        Person.prototype.job=‘Software engineer‘;
        Person.prototype.sayName=function(){
            alert(this.name);
        }
        var person1 = new Person();
        alert(person1.hasOwnProperty(‘name‘));//false
        alert(‘name‘ in person1);//true
        person1.name = ‘wangwu‘;
        alert(person1.name);//wangwu
        alert(person1.hasOwnProperty(‘name‘));//true
        alert(‘name‘ in person1);//true

  同时使用hasOwnProperty()和in操作符,就可以确定该属性到底存在与实例中还是原型中。

        function hasPrototypeProperty(object,name){
            return !object.hasOwnProperty(name) && (name in object);
        }    

  只要in操作符返回true而hasOwnProperty()返回false,就可以确定属性是原型中的属性。

  在使用for-in循环时,返回的是所有能过通过对象访问的、可枚举的属性,其中既包括存在实例中的属性,也包括存在于原型中的属性。

  要取得对象上所有的可枚举的实例属性,可以使用ECMAScript5的Object.keys()方法;

        function Person(){
        }
        Person.prototype.name=‘lisi‘;
        Person.prototype.age=23;
        Person.prototype.job=‘Software engineer‘;
        Person.prototype.sayName=function(){
            alert(this.name);
        }
        var keys = Object.keys(Person.prototype);
        alert(keys);//name,age,job,sayName
        var person1 = new Person();
        person1.name=‘zhangsan‘;
        person1.age=21;
        var pkeys = Object.keys(person1);
        alert(pkeys);//name,age

  如果你想要得到所有的实例属性,无论它是否可枚举,都可以使用Object.getOwnPropertyNames()方法。

        var keys = Object.getOwnPropertyNames(Person.prototype);
        alert(keys);//constructor,name,age,job,sayName
时间: 2024-10-14 04:59:15

js的原型模式的相关文章

js设计模式-原型模式

1.Object.create(obj,[]) 创建一个以obj为原型的对象. function res4(){}; res4.prototype=Object.create(myobj, { // foo会成为所创建对象的数据属性 foo: { writable:true, configurable:true, value: "hello" }, // bar会成为所创建对象的访问器属性 bar: { configurable: false, get: function() { re

[js]js设计模式-原型模式

构造函数模型- 对象的属性和方法每人一份 function createJs(name, age) { this.name = name; this.age = age; this.writeJs = function () { console.log(this.name, this.age) } } p1 = new createJs("maotai", 22); p1.writeJs(); p2 = new createJs("maotai2", 23); p2

面向对象JS基础讲解,工厂模式、构造函数模式、原型模式、混合模式、动态原型模式

什么是面向对象?面向对象是一种思想!(废话). 面向对象可以把程序中的关键模块都视为对象,而模块拥有属性及方法.这样我们如果把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作.接下来将为大家讲解在JS中面向对象的实现. 工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,而由于在ECMAScript中无法创建类,因此用函数封装以特定接口创建对象.其实现方法非常简单,也就是在函数内创建一个对象,给对象赋予属性及方法再将对象返回即可. function createBlog(

JS面向对象(1)——构造函数模式和原型模式

1.构造函数模式 构造函数用来创建特定的类型的对象.如下所示: function Person(name,age,job){ this.name=name; this.job=job; this.age=age; this.sayName=function(){ alert(this.name); }; } var person1=new Person('nick',20,'student');var person2=new Person('nick',20,'student');alert(p

JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模)

什么是面向对象?面向对象是一种思想!(废话). 面向对象可以把程序中的关键模块都视为对象,而模块拥有属性及方法.这样我们如果把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作.接下来将为大家讲解在JS中面向对象的实现.   工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,而由于在ECMAScript中无法创建类,因此用函数封装以特定接口创建对象.其实现方法非常简单,也就是在函数内创建一个对象,给对象赋予属性及方法再将对象返回即可. ? 1 2 3 4 5 6 7 8

js设计模式:工厂模式、构造函数模式、原型模式、混合模式

一.js面向对象程序 var o1 = new Object(); o1.name = "宾宾"; o1.sex = "男"; o1.age = "27"; o1.msg = function(){ console.log("姓名:"+this.name+"  性别:"+this.sex+"  年龄:"+this.age); } var o2 = new Object(); o2.nam

【JavaScript】 JS面向对象的模式与实践 (重点整治原型这个熊孩子 (/= _ =)/~┴┴ )

参考书籍 <JavaScript高级语言程序设计>—— Nicholas C.Zakas <你不知道的JavaScript>  —— KYLE SIMPSON 在JS的面向对象编程中,我们最为关注的是两种行为,一是创建对象,二是类继承 JS创建对象 构造函数模式创建对象 第一种创建对象的方式是构造函数模式 如下所示, 将构造函数中的属性和方法赋给一个新对象 /** * description: 构造函数模式创建对象 */ function Type (p) {   this.par

关于js的设计模式(简单工厂模式,构造函数模式,原型模式,混合模式,动态模式)

<1>工厂模式 简单来说就是封装后的代码,简单的工厂模式是很好理解的,关于它的作用,就是利用面向对象的方法,把一些对象封装,使一些占用空间多的,重复的代码封装起来.实现方法非常简单,也就是在函数内创建一个对象,给对象赋予属性以及方法再将对象返回即可. function creatper(name,age){ var per=new Object(); //原料 //加工 per.name=name; per.age=age; per.sayHi=function(){ console.log(

js中创建对象方式----原型模式

一.什么是原型模式 在js中,创建对象的方式有工厂模式和构造函数模式等: 而构造函数模式最大的问题在于:构造函数中的每个方法都需要在实例对象中重新创建一遍,不能复用,所以为了解决这一个问题,就需要使用原型模式来创建对象.原型模式是把所有实例共享的方法和属性放在一个叫做prototype(原型)的属性中 ,在创建一个函数时都会有个prototype属性, 这个属性是一个指针,指向一个对象,是通过调用构造函数而创建的那个对象实例的原型对象. // 构造函数 function Person() {};