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("Lucy",30,"Software Engineer");
var person2 = createPerson("Greg",30,"Doctor");

优势:可多软调用,每次都归一个含有三只属性一个智的对象,避免出现多独一般对象的题目。

缺点:无法断定目标的档次。   

2.构造函数模式

同其它函数的区分在于调用方式,通过new操作符来调用,如果不用new,跟其它函数没有呀界别。

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

作为构造函数调用:
var person = new Person("Greg",30,"Doctor");
person.sayName(); //Greg
作为普通函数调用:
Person("Greg",30,"Doctor");  //添加到window
window.sayName();或者sayName();  //Greg
在另一个对象作用域中调用
var o = new Object();
Person.call(o,"Kristen",30,"Nurse");
o.sayName();  //Kristen

优势:

(1)创建于定义的构造函数,意味着可以用实例标识也同样种植特定的色,是强了工厂模式之地方。

alert(person1 instanceof Person);  //true

alert(person1 instanceof Object);  //true

(2)每个方法还使每个实例上更创设同全方位,例子中person1和person2都起一个sayName()的不二法门,但是简单独主意不是和一个Function实例。注:ECMAScript中之函数是目标,因此各个定义一个函数,也就实例化一个靶。

等价于:this.sayName = new Function(“alert(this.name)”);

避免方案:

function Person(name,age,job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = sayName;
}
function sayName(){
    alert(this.name);
}  //弊端:全局作用域的函数实际只能被某个对象调用,让全局作用域名不副实;若对象需要定义很多方法,就对应很多全局方法。

3.原型模式

function Person() {}
Person.prototype.name = "Lucy";
Person.prototype.age = 30;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
    alert(this.name)
}
var person1 = new Person();
person1.sayName();  //Lucy

//简单语法

function Person() {}
Person.prototype = {
        constructor: Person,  //确保constructor属性指向Person函数
        name: "Lucy",
        age: 30,
        sayName: function(){
                alert(this.name)
        }
};
var person1 = new Person();
person1.sayName();  //Lucy
注:若将var person1 = new Person();提升到第二行,则报错,因为重写原型对象切断了现有实例和新原型之间的联系,它们的引用任然是最初的原型。

优势:可以为具备实例共享它所蕴含的性质和措施。

规律:只要创造了一个函数,即为该函数创造一个prototype属性,这个特性指向函数的原型对象。默认情况下,所有的原型对象都见面活动获取一个constructor(构造函数)属性,这个特性指向函数。

ECMAScript 1

方法:

确定原型与实例关系的蝇头独章程:

(1)instanceof操作符

person1 instanceof Person  //true

(2)isPropotypeOf()方法

Person.prototype.isPrototypeOf(person1)  //true

其他:

Object.getPrototypeOf()方法:Object.getPrototypeOf(person1)返回[[prototype]]的值

hasOwnProperty():检测一个特性是否在叫实例中

in操作符:只要透过对象会访问到性,就返回true,同齐结即可确定拖欠属性是有被对象吃还是原型中。

坏处:原型模式之享有的性能让广大实例共享,即出于该共享本质所赋;尤其是引用类型值的性质(即[“red”,”green”,”yellow”])。

4.重组以构造函数模式及原型模式(认可度高,推荐)

便构造函数模式用于定义实例属性,而原型模式用于定义方法和共享属性

function Person(name, age, job){
    this.name = name; 
    this.age = age; 
    this.job = job; 
    this.friends = ['Shelby', 'Court'];
}

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

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

person1.friends.push('Van');
alert(person1.friends);  //'Shelby,Court,Van'
alert(person1.friends);  //'Shelby,Court'

短:有其它OO语言开发经历的人手于目独立构造函数和原型时,有些迷惑。

5.动态原型模式

拿装有信息都封装在了构造函数中,通过当构造函数中初始化原型(仅于产生必要的动静下)。

function Person(name, age, job){
    this.name = name; 
    this.age = age; 
    this.job = job; 
    //方法
    if(typeof this.name != function){
         Person.prototype.sayName = function(){
              alert(this.name);  
         }  
    }
}       

优势:对于下这种模式开创的靶子,还可以行使instanceof操作符来确定其的型。即
person1 instanceof Person; //true

6.寄生构造函数模式

除了用new操作符外,其他与工厂模式一模一样。

function SpecialArray(){
    var values = new Array();
    //添加值
    values.push.apply(values, arguments);
    //添加方法
    values.toPipedString = function(){
        return this.join('|');
    }
    //返回数组
    return values;
} 
var colors = new SpecialArray('red','blue','green');
alert(colors.toPipedString()); //'red|blur|green'

症结:返回的函数和构造函数或者说与构造函数的原型属性一点关联尚未,跟工厂模式一样的,不能够依赖instanceof操作符来确定项目。

7.稳构造函数模式

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

优势:除了调用sayName方法外无别的方式可以看到该数据成员,适合安全环境被,防止数据让别程序改动时使用。

和寄生构造函数的界别ECMAScript:

(1)新创建目标的实例方法无以this

(2)不使new操作符调用构造函数  

症结:与寄生构造函数类似,操作符instanceof对之目标不起作用。