ECMAScript创建对象的几种植模式

1.工厂模式

function createPerson(name,age,job){
   var o=new Object();
   o.name=name;
   o.age=age;
   o.job=job;
   o.sayName=function(){
   alert(this.name);  
  };
  return o; 
}
var person1=createPerson("Nicholas",29,"Software Engineer");
var person2=createPerson("Greg",27,"Doctor");

亮点:解决了创办多只一般对象的题材。

症结:没有缓解对象识别问题(即什么理解一个对象的类别)

2.构造函数模式

function Person(name,age,job){
   this.name=name;
   othis.age=age;
   this.job=job;
   this.sayName=function(){
       alert(this.name);  
  }; 
}
var person1=new Person("Nicholas",29,"Software Engineer");
var person2=new Person("Greg",27,"Doctor");

以及工厂模式相比,这里没有显式地创建对象;直接以性能和法给给了this对象;没有return语句。按照老,构造函数始终都应该以一个雅写字母开头,而休构造函数应该因为一个小写字母开头。在这个例子中,person1和person2各自保存在Person的一个两样实例,这简单个目标都发出一个constructor(构造函数)属性。任何函数,只要通过new操作来调用,那她就可以看做构造函数;而别函数,如果无通过new操作符来调用,那它们跟普通函数就没什么不同。

优点:创建于定义之构造函数意味着前得以将它们的实例标识为同栽特定的路;而立正是构造函数模式大了工厂模式的地方。

症结:每个方法还如在每个实例上重复创设同尽。

改进:

function Person(name,age,job){
   this.name=name;
   this.age=age;
   this.job=job;
   this.sayName=sayName;
}
function sayName(){
       alert(this.name);  
  }; 
var person1=new Person("Nicholas",29,"Software Engineer");
var person2=new Person("Greg",27,"Doctor");

用sayName()函数的概念转移到了构造函数外部。而构造函数内部,我们将sayName属性设置成等于全局的sayName函数。这样一来,由于sayName包含的是一个对准函数的指针,因此person1和person2对象就共享了以大局作用域中定义的和一个sayName()函数。可是一旦目标要定义很多办法,那么就算设定义很多大局函数,于是我们以此自定义的援类型就丝毫从未封装性可言。

3.原型模式

function Person(){
}
Person.prototype.name="Nicholas";
Person.prototype.age=29;
Person.prototype.job="Software Engineer";
Person.prototype.sayName=function(){
    alert(this.name);
};
var person1=new Person();
person1.sayName();
var person2=new Person();
person2.sayName();
alert(person1.sayName==person2.sayName); //true  

咱创建的每一个函数都发生一个prototype(原型)属性,这个特性是一个指南针,指向一个靶,而以此目标的用处是包含可以由特定项目的有着实例共享的特性和道。不过要判的的确关键之少数尽管是,这个连续在吃实例与构造函数的原型对象之间,而非是在被实例与构造函数之间。

在代码读取某个对象的之一属性时,都见面实行同样糟糕寻,目标是具备给定名字的特性。搜索首先由目标实例本身开始。如果当实例中找到了有着给定名字的性质,则归该属性的价值;如果没有找到,则连续查找指针指向的原型对象,在原型对象吃查找具有给定名字的性能。

function Person(){
}
Person.prototype.name="Nicholas";
Person.prototype.age=29;
Person.prototype.job="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);//"Nicholas"——来自原型

运hasOwnProperty()方法好检测一个特性是在为实例中,还是存在于原型中。它是打object继承来之,只于吃定属性存在被对象实例中时,才会回来TRUE。上面例子中person1重写了name属性,故调用person1.hasOwnProperty(“name”);时才见面回到true;

大家该专注到了,前面例子中每添加一个性和艺术就是假设讹一全体Person.prototype,为缩减非必要的输入,也为从视觉及又好地卷入原型的机能,更宽泛的方式是故一个饱含有属性和法的目标字面量来重新写满原型对象。

function Person(){
}
Person.prototype={
    name:"Nicholas",
    age:29,
    job:"software engineer",
    sayName:function(){
        alert(this.name);
  }  
};

但上面的法门会如constructor属性不再对Person了,为者可以在Person.prototype添加一律句子,constructor:Person,以管教通过该属性可以拜到当的价。

瑜:可以吃具有目标实例共享它所富含的实例和方式。换句话说,不必在构造函数中定义对象实例的音信,而是可以用这些信息一直长到原型对象中。

缺陷:它大概了为构造函数传递初始化参数就同环节,结果具有实例在默认情况下都以抱一致的属于性值。这种共享于函数非常得体,对于那些饱含基本值的性能为说得过去,但对此富含引用类型值的性质来说,问题便比较突出了。如下:

function Person(){
}
Person.prototype={
constructor:Person,
name:"Nicholas",
age:29,
job:"Software Engineer",
friend:["one","two"],
sayName:function(){
    alert(this.name);
    }
};
var person1=new Person();
var person2=new Person();

person1.friend.push("three");

alert(person1.friend); //"one,two,three"
alert(person2.friend); //"one,two,three"
alert(person1.friend===person2.friend);//true

立也是非常少看有人独使用原型模式的故所在。

4.结缘以构造函数模式与原型模式

function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.friends=["one","two"];
}

Person.prototype={
    constructor:Person,
    sayName:function(){
    alert(this.name);
  }
}

var person1=new Person("Nicholas",29,"softwarre Engineer");
var person2=new Person("Greg",27,"Doctor");

person1.friends.push("three");
alert(person1.friends);    //"one,two,three"
alert(person2.friends);    //"one,two"
alert(person1.friends==person2.friends);   //false
alert(person1.sayName==person2.sayName);    //true

这种结合模式ECMAScript受到构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的性。这种重组模式是在ECMAScript中运用最常见,认同度最高的一模一样种创建于定义类型的艺术。

5.动态原型模式

function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    if(typeof this.sayName !="function"){
        Person.prototype.sayName=function(){
            alert(this.name);
    }
  }
}
var friend=new Person("Nicholas",29,"Software Engineer");
friend.sayName();

此只有于sayName()方法不存在的场面下才会将它们上加到原型中。这段代码只有在头版调用的当儿才见面履。

6.寄生构造函数模式

function Person(name,age,job){
    var o=new Object();
    o.name=name;
    o.age=age;
    o.job=job;
    o.sayName=function(){
        alert(this.name);
  };
    return o;
}

var friend=new Person("Nicholas",29,"Software Engineer");
friend.sayName();

寻常在前方几种模式都非适用的情下,可以动用寄生构造函数模式。这种模式之着力思想是创办一个函数,该函数的来意只是包创建对象的代码,然后再次回新创造的目标。关于寄生构造函数模式,有好几万一证明:首先,返回的对象及构造函数或者与构造函数的原型属性之间没有关系;也就是说,构造函数的返的对象同以构造函数外部创建的目标没啊不同。为夫不可知依赖instanceof操作符来确定目标类型。

7.妥善构造函数模式

function Person(name,age,job){
    var o=new Object();
    //可以在这里定义私有变量和函数
    o.sayName=function(){
        alert(name);
  };
    return o;
}

var friend=Person("Nicholas",29,"Software Engineer");
friend.sayName();

Douglas
Crockford发明了javascript中的妥善对象是概念。所谓稳妥对象,指的凡未曾集体性质,而且该艺术为未引用this的目标。稳妥对象极其符合在局部安之条件遭到(这些条件会禁止使用this和new)时用。稳妥构造函数遵循以及寄生构造函数类似的模式,但生一定量接触不同:一凡是初创办目标的实例不引用this;二凡匪应用new操作符调用构造函数。在点的事例中,除了sayName()方法外,没有别的办法得以看该数据成员。