js 创建对象的七种模式

一、工厂模式

function createPerson(name,age){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.sayName = function(){
        alert(this.name)
    }
    return o;
}
var person1 = createPerson('小明',18);
var person2 = createPerson('小红',16);
console.log(person1);//Object {name: "小明", age: 18, sayName->"小明"}
console.log(person2);//Object {name: "小红", age: 16, sayName->"小红"}

二、构造函数模式

function Person(name,age){
    this.name = name;
    this.age = age;
    this.sayName = function(){
        alert(this.name)
    }
}
var person1 = new Person('小明',18);
var person2 = new Person('小红',16);
console.log(person1);//Person {name: "小明", age: 18, sayName->"小明"}
console.log(person2);//Person {name: "小红", age: 16, sayName->"小红"}
console.log(person1.constructor);//Person
console.log(person2.constructor);//Person
console.log(person1 instanceof Object);//true
console.log(person1 instanceof Person);//true
console.log(person2 instanceof Object);//true
console.log(person2 instanceof Person);//true

构造函数的问题

this.sayName = function(){alert(this.name)};
//等价于
this.sayName = new Function("alert(this.name)");
//所以,每次实例化的Person都创建了不同的sayName方法,它们完成同样的任务这样做事没有必要的
person1.sayName() == person2.sayName() //false

一种解决办法

function Person(name,age){
    this.name = name;
    this.age = age;
    this.sayName = sayName;
}
function sayName(){
    alert(this.name)
}
//person1.sayName() == person2.sayName() //true
//不过这样做并没有封装性可言

三、原型模式

function Person(){}
Person.prototype.name = '小明';
Person.prototype.age = 18;
Person.prototype.sayName = function(){
    alert(this.name)
}
var person1 = new Person();
var person2 = new Person();
console.log(person1);
person1.sayName();//小明
person2.sayName();//小明
person1.sayName == person2.sayName;//true
console.log(Person.prototype.isPrototypeOf(person1));//true
console.log(Person.prototype.isPrototypeOf(person2));//true
console.log(Object.getPrototypeOf(person1) == Person.prototype);//true
console.log(Object.getPrototypeOf(person2).name);//小明

//判断来源
console.log(person1.name);//小明 --来自原型
console.log(person1.hasOwnProperty('name'));//false
console.log('name' in person1);//true
person2.name = '小红';
console.log(person2.name);//小红 --来自实例
console.log(person2.hasOwnProperty('name'));//true
console.log('name' in person2);//true
delete person2.name;
console.log(person2.name);//小明 --来自原型
console.log(person2.hasOwnProperty('name'));//false
console.log('name' in person2);//true

//枚举 - Object.keys
console.log(Object.keys(Person.prototype)) // ["name","age","sayName"]
person2.name = '小红';
console.log(Object.keys(person2)) // ["name"]

//枚举 - getOwnpropertyNames
console.log(Object.getOwnPropertyNames(Person.prototype));//["constructor", "name", "age", "sayName"];
console.log(Object.getOwnPropertyNames(person2))//["name"]

//更简单的原型方法
function Person(){}
Person.prototype = {
    constructor: Person,//字面量模式不调用构造函数方法,必要时这里需手动指定构造函数为Person
    name: '小明',
    age: 18,
    sayName : function(){
        alert(this.name)
    }
}

原型模式的问题

function Person(){};
Person.prototype = {
    constructor: Person,
    name: '小明',
    age: 18,
    friends: ['小红','小强']
}
var person1 = new Person();
var person2 = new Person();
console.log(person1.friends);//['小红','小强']
person2.friends.push('张三');
console.log(person1.friends);//['小红','小强','张三']
console.log(person2.friends);//['小红','小强','张三']
console.log(person1.friends == person2.friends); //true
//原型属性中包含一个引用类型值friends数组,所有实例中friends指向同一个数组,当其中一个发生修改,立即体现到其他实例中

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

function Person(){
    this.name = '小明';
    this.age = 18;
    this.friends = ['小红','小强'];
};
Person.prototype = {
    constructor: Person,
    sayName : function(){
        alert(this.name);
    }
}
var person1 = new Person();
var person2 = new Person();
console.log(person1.friends);//['小红','小强']
person2.friends.push('张三');
console.log(person1.friends);//['小红','小强']
console.log(person2.friends);//['小红','小强','张三']
console.log(person1.friends == person2.friends); //false
//这样避免了原型模式的问题

五、动态原型模式

function Person(name,age){
    this.name = name;
    this.age = age;
    if(typeof this.sayName != "function"){
        Person.prototype.sayName = function(){
            alert(this.name);
        }
    }
}
var person1 = new Person('小明',18);
person1.sayName();//小明

六、寄生构造函数模式

function Person(name,age){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.sayName = function(){
        alert(this.name);
    }
    return o;
}
var person1 = new Person('小明',18);
person1.sayName();//小明

寄生构造函数demo

function SpecialArray(){
    var values = new Array();
    values.push.apply(values,arguments);
    values.tojoin = function(){
        return this.join('|');
    }
    return values;
}
var colors = new SpecialArray('red','yellow','blue');
console.log(colors.tojoin());//red|yellow|blue

七、稳妥构造函数模式

function Person(name,age){
    var o  = new Object();
    o.sayName = function(){
        alert(name)
    }
    return o;
}
var person1 = Person('小明',18);
person1.sayName();//这里的name除了sayName方法可以访问,没有任何其他方式可以访问和修改,并且省略了this和new关键字
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值