JS创建对象的归纳

JS创造对象主要有:工厂模式、构造函数模式、原型模式、组合模式(构造函数+原型)、动态原型模式、寄生构造函数模式、稳妥构造函数模式。现主要区分概念以及各方式的优缺点。

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 person = createPerson("Nico",15,"Engineer");
person instanceof createPerson; //false

优点:解决了用Obeject构造函数或对象字面量方式带来大量重复代码的问题。

缺点:没有解决对象识别问题(即怎样知道一个对象的类型)

2.构造函数模式

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("Nico",15,"Engineer");
var person2 = new Person("Greo",19,"Engineer");

person1 instanceof Person; //true

优点:解决了对象识别问题(优于工厂模式)

缺点:可能要定义多个全局函数,但有只能被某个对象调用,无封装性

3.原型模式

function Person(){}
Person.prototype = {
    constructor: Person, //会导致变成可枚举,而原生的construtor不可枚举;不设置该属性,则construtor会指向Object
    name: "Nico",
    age: 15,
    job: "Engineer",
    friend: ["Gero","Hannah"],
    sayName: function(){
        alert(this.name);
    }
}

//重设构造函数,只适用于ES5兼容的浏览器
Object.defineProperty(Person.prototype, "constuctor",{
    enumerable: false,
    value: Person
})

var person1 = new Person();
var person2 = new Person();
person1.friend.push("Maro");
console.log(person2 .friend);  // ["Gero", "Hannah", "Maro"]

优点:所有对象实例共享原型的属性和方法

缺点:引用类型值的属性(例如数组),也被共享了

4.组合模式(构造函数+原型)

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friend =["Gero","Hannah"]
}

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

var person1 = new Person("Nico",15,"Engineer");
var person2 = new Person("Gero",19,"Engineer");

person1.friend.push("Maro");
console.log(person1.friend); //["Gero", "Hannah", "Maro"]
console.log(person2.friend); //["Gero", "Hannah"]
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(){
            alert(this.name);
        }
    }
}

var person1 = new Person("Nico",15,"Engineer");
console.log(person1.sayName());  //Nico
person1 instanceof Person;  //true

优点:几乎完美

缺点:若在已经创建实例的情况下,使用对象字面量重写原型,会切断现有实例和新原型之间的联系

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 person = new Person("Nico",15,"Engineer");
person instanceof Person; //false

与工厂模式基本一样,除了用了new操作符

例如:

function SpecialArray(){
    var value = new Array();
    value.push.apply(value, arguments);
    value.toPipeString = function(){
        return this.join("|");
    }
    return value;
}

var array = new SpecialArray("A","B","C");
console.log(array.toPipeString());  // “A|B|C”
array instanceof SpecialArray; //false

优点:可用在不能直接修改构造函数,又想创建一个具有额外方法的对象

缺点:返回的对象与构造函数或者与构造函数的原型属性之间并没有关系,不能依赖instanceof来确定对象类型,可使用其他模式时,不推荐该模式

7.稳妥构造函数模式

function Person(name, age, job){
 var o = new Object();
 o.name = name;
 o.age = age;
 o.job = job;
 o.sayName = function(){
   alert(name);
 }
 return o;
}
var person = Person("Nico",15,"Engineer");
person instanceof Person; //false

除了使用sayName()方法之外,没有其他方法访问name的值

优点:适合安全环境中,禁止使用this,new的环境中,或者防止数据被其他应用程序改动;

缺点:同寄生构造函数

------------------------------------------------------------------------------

in : 是否能够通过对象访问给定属性,无论该属性存在于实例中还是原型中

hasOwnProperty() : 只在属性存在于实例中时,才返回true

判断属性存在对象实例中,还是原型中:

//是否在原型上
function isHasPrototypeProperty(object, name){
    return !object.hasOwnProperty(name) && (name in object);
}

------------------------------------------------------------------------------

Object.keys() :得到对象的实例属性(不包括不可枚举)

Object.getOwnPropertyName() :得到对象的实例属性,包括不可枚举的constructor

Object.keys(Person.prototype); //"name,age,job,sayName"
Object.getOwnPropertyName(Person.prototype);//"constructor,name,age,job,sayName"





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值