一:创建对象
1 工厂模式

 function createPerson(name, age, jod){
     var obj = new Object();
     obj.name = name;
     obj.age = age;
     obj.job = job;
     obj.sayName = function(){
         console.log(this.name);
     };
     return obj;
 }

 var person1 = createPerson('NEVAR', 23, 'Front-end Engineer');
 var person2 = createPerson('Amy', 27, 'Doctor');

2 构造函数模式

 function Person(name, age, job){
     this.name = name;
     this.age = age;
     this.job = job;
     this.sayName = function(){
         console.log(this.name);
     }
 }

 var person1 = new Person('NEVAR', 23, 'Front-end Engineer');
 var person2 = new Person('Amy', 27, 'Doctor');
 //person1和person2都是Person的不同实例。
 alert(person1.constructor == Person); //true
 alert(person2.constructor == Person); //true
 //即是Object的实例也是Person的实例
 alert(person1 instanceof Object); //true
 alert(person1 instanceof Person); //true
 //构造函数产生的是两个不同实例,同名函数是不相等的
 alert(person1.sayName == person2.sayName); //false

3 原型模式

 function Person(){
 }

 Person.prototype.name = 'NEVAR';
 Person.prototype.age = 23;
 Person.prototype.job = 'Front-end Engineer';
 Person.prototype.sayName = function(){
     console.log(this.name);
 };

 var person1 = new Person();
 person1.sayName(); //NEVAR

 var person2 = new Person();
 person2.sayName; //NEVAR

 console.log(person1.sayName == person2.sayName);// true

 var person3 = new Person();
 person3.name = 'PP';
 console.log(person3.name); //PP 来自实例

 delete person3.name;
 console.log(person3.name); //NEVAR 来自原型

 alert(person1.hasOwnProperty("name")); //false 来自原型
 alert(person3.hasOwnProperty("name")); //true  来自实例

 alert("name" in person1); //true in操作符的使用

 function hasPrototypeProperty (obj, name){
     return !obj.hasOwnProperty(name) && (name in obj)
 }
 //判断属性来自实例 真 然后取反 
 //并且name属性存在于obj原型链上 说明这个 属性是属于prototype的

 alert(hasPrototypeProperty(person1,'name')) // true
 alert(hasPrototypeProperty(person3,'name')) // false

 alert(Object.keys(Person.prototype)) //"name,age,job,sayName" 
 //Person的可枚举属性

不过以上方法太过于麻烦 每次都要写重复的prototype

 function Person(){
 }

 Person.prototype = {
     name : 'NEVAR',
     age : '23',
     job : 'Front-end Engineer',
     sayName : function(){
         console.log(this.name);
     }
 };

constructor 属性不再指向Person 了 指向Object

var friend = new Person();
 alert(friend instanceof Object); //true
 alert(friend instanceof Person); //true
 alert(friend.constructor == Person); //false
 alert(friend.constructor == Object); //true

于是可以这样

 Person.prototype = {
     constructor : Person,
     name : 'NEVAR',
     age : '23',
     job : 'Front-end Engineer',
     sayName : function(){
         console.log(this.name);
     }
 };

原型的动态性

var friend = new Person();

 Person.prototype.sayHi = function(){
     alert('Hi');
 }
friend.sayHi();//Hi
//这时没有问题,如果我们重写原型对象 那么情况就不一样了
function Person(){
}
var friend = new Person();
Person.prototype = {
constructor: Person,
name : "NEVAR",
age : 23,
job : "Front-end Engineer",
sayName : function () {
alert(this.name);
}
};
friend.sayName(); //error

重写原型对象切断了现有原型与任何之前已经存在的对象实例之间的联系;它们引用的仍然是最初的原型。

原型模式也不是没有缺点。首先,它省略了为构造函数传递初始化参数这一环节,结果所有实例在默认情况下都将取得相同的属性值

对于那些包含基本值的属性倒也说得过去,毕竟(如前面的例子所示),通过在实例上添加一个同名属性,可以隐藏原型中的对应属性。然而,对于包含引用类型值的属性来说,问题就比较突出了

function Person(){
}
Person.prototype = {
constructor: Person,
name : "Nicholas",
age : 29,
job : "Software Engineer",
friends : ["Shelby", "Court"],
sayName : function () {
alert(this.name);
}
};
var person1 = new Person();
var person2 = new Person();
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Court,Van"
alert(person2.friends); //"Shelby,Court,Van"
alert(person1.friends === person2.friends); //true

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(){
         console.log(this.name);
     }
 }

 var person1 = new Person('NEVAR', 23, 'Front-end Engineer');
 var person2 = new Person('Amy', 27, 'Doctor');

 person1.friends.push('Van');

 console.log(person1.friends) //'Shelby,Court,Van'
 console.log(person2.friends) //'Shelby,Court'
 console.log(person1.friends === person2.friends); // false
 console.log(person1.sayName === person2.sayName); //true

5动态原型模式
它把所有信息都封装在了构造函数中,而通过在构造函数中初始化原型(仅在必要的情况下),又保持了同时使用构造函数和原型的优点。换句话说,可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    if(typeof this.sayName != function){
        Person.prototype.sayName = function(){
            console.log(this.name);
        }
    }
}

 var person1 = new Person('NEVAR', 23, 'Front-end Engineer');
 friend.sayName();

6寄生构造函数模式

//不使用this和new
function Person(name, age, job){
    //创建要返回的对象
    var o = new Object();
    //可以在这里添加私有变量和函数

    //添加方法
    o.sayName = function(){
        console.log(name);
    }
    return o;
}

注意,在以这种模式创建的对象中,除了使用sayName()方法之外,没有其他办法访问name 的值


nevar
42 声望1 粉丝