Javascript的创建型设计模式

在Javascript中,创建一个对象可以用Object构造函数或者对象字面量,但是,如果要创建很多对象,这就会产生大量的代码,很繁琐。所有,就有了以下的创建对象的设计模式。

一、工厂模式

  1. 工厂模式:用函数封装特定接口对象细节,返回一个对象,来看一个例子:
function person(name,age){
        var o = new Object();
        o.name = name;
        o.age = age;
        o.sayName = function () {
            alert(this.name)
        }
        return o
    }
    var person1 = person("wahaha",11)
    person1.sayName();  //wahaha
    alert(person1 instanceof person);  //false

 问题来了,person1不属于person类,没有了对象识别,因为内部是返回来Object类型对象。所以为了解决这个,大牛们又发明了构造函数模式

二、构造函数模式

  1. 构造函数模式没有了return返回值和new一个Object,和用this指向当前的作用域,下面来看个例子:
function Person(name,age){
       this.name = name;
       this.age = age;
       this.sayName = function () {
           alert(this.name)
       }
    }
    var person1 = new Person("wahaha",11)
    person1.sayName();  //wahaha
    alert(person1 instanceof Object); //true

构造函数模式改正了工厂模式的确定,让person1有了对象识别,并且用了new关键字创建,所以有了一下引声:

  • 每个实例都有一个constructor属性,这属性指向对象person的 
  • 将构造函数当作函数使用:可以call()和apply()来改变作用域

构造函数模式也不是没有缺点,它里面的方法不能共享,每一个实例都有相同的方法,这样很耗效率,所以有人又发明了原型模式

三、原型模式

  1. 原型模式:创建的每个函数都会有一个prototype属性,这属性是个指针,指向对象。这属性是每个对象的实例共享的对象。来看下代码:
function Person(){
    }
    Person.prototype.name = 'wahaha';
    Person.prototype.age = 29;
    Person.prototype.sayName = function () {
        alert(this.name)
    }
    var person1 = new Person();
    var person2 = new Person();
    alert(person1.sayName == person2.sayName);  //true

这样就能共享一个方法了,这里还有一些知识需要说下:

  • 每个实例都有一个[[prototype]]属性,这属性没有标准访问,但是浏览器都支持这个属性。这属性 指向的是原型:Person.prototype,知直接指向原型,和构造函数没关系。
  • 原型都有一个constructor属性指向对象Person。
  • 每个实例需要属性或方法时候都会进行两次搜索。注意的是:原型里面的属性的值不能通过实例相同属性来改变,并且如果实例上有相同属性名则会屏蔽原型的属性。

这又有一个问题:如果过原型里面需要很多属性和方法,则会很繁琐,所以用对象字面量可以重写原型

 function Person(){
    }
    Person.prototype = {
        name : 'wahaha',
        age : 11,
        sayName :function () {
            alert(this.name)
        }
    }
    var person1 = new Person();
    person1.sayName(); //wahaha

 但是重写了原型,constructor的指向不再是Person,所以要在对象字面量中加多一条语句指向Person,

constructor:Person,

 注意的是:实例的[[prototype]]属性的值都改变了,是指向Person.prototype,但是不是指向重写的Person.prototype

下面还有一些关于原型模式用到的方法:

1.isPrototypeof():确定实例是否与原型对象存在这种关系

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

2.getPrototypeof (Object);返回实例[[prototype]]的值

3.hasOwnPrototype():判断一个属性或者方法是否存在于实例上

alert(person1.hasOwnProperty('name'))  //false,存在则true

 4.Object.keys(原型对象):列出可以枚举的属性(包括实例和原型)

5.Object.getOwnPrototypeNames(原型对象):列出所有属性(包括实例和原型)

这里顺便写一下[[Enumerable]]这属性吧

[[Enumerable]]是标记原型属性是否可枚举,constructor属性默认是false。

原型模式也有缺点:属性是数组的话就不能了,因为每个实例push一个进去,其他实例都受影响。

四、组合使用构造函数模式和原型模式

这是最佳方案:构造函数定义实体自己特有的方属性,原型模式用来定义全部实例共有的属性和方法

五、动态原型模式

动态原型模式是在原型初始化的时候,把方法或者属性写进原型

function Person(name,age){
        this.age = age;
        this.name = name;
        if(typeof this.sayName != "function"){
            Person.prototype.sayName = function () {
                alert(this.name)
            }
        }
    }

    var person1 = new Person("wahaha",11);
    person1.sayName();

 

六、稳妥构造函数模式

如果考虑安全性的话用这函数模式,因为不可以用new和this

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值