JavaScript创建对象的方式

工厂模式

        创建函数来封装特定的接口和创建对象的细节。函数可以通过接受对象来创建一个包含属性和方法的对象,可以反复的调用函数。

优点:增加了代码的复用性 缺点:无法识别对象类型

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');

构造函数模式

可以通过创建自定义的构造函数,来定义自定义对象类型的属性和方法。

与工厂模式的不同:没有显式地创建对象,直接将属性和方法赋给了this对象,没有return语句

 优点:可以将它的实例标识为一种特定的类型

缺点:每个方法都要在实例上创建一遍,浪费内存空间

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.jog = job;
    this.sayName = function(){
        alert(this.name);
    };
}
var person1 = new Person('Nicholas',29,'Software Engineer');
var person2 = new Person('Greg',27,'Doctor');
内存空间不同
console.log(person1.sayName === person2.sayName);//false

改进方法:把函数定义转移到构造函数外部

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.jog = job;
    this.sayName = sayName;
}
function sayName(){
    alert(this.name);
};
var person1 = new Person('Nicholas',29,'Software Engineer');
var person2 = new Person('Greg',27,'Doctor');
console.log(person1.sayName === person2.sayName);//true

优点:解决了方法被重复创建的问题

缺点:在全局作用域中定义的函数实际上只能被某个对象调用,这让全局作用域有点名不副实。而且,如果对象需要定义很多方法,就要定义很多全局函数,会污染全局空间,这个自定义的引用类型没有封装性可言了。

原型模式

        使用原型对象,可以让所有实例共享它的属性和方法。换句话说,不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中

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();//"bai"

var person2 = new Person();
person2.sayName();//"bai"

alert(person1.sayName == person2.sayName);//true

缺点:引用类型值属性会被所有的实例对象共享并修改

更简单的原型语法

为了减少不必要的输入,也为了从视觉上更好地封装原型的功能,用一个包含所有属性和方法的对象字面量来重写整个原型对象

function Person(){
}

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

var person1 = new Person();
person1.sayName();//"Nicholas"

alert(person1.constructor === Person);//false
alert(person1.constructor === Object);//true

缺点:constructor无法在指向Person函数,可以在原型函数中设置constructor(constructor:Person)来解决这个问题

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

        创建自定义类型的最常见方式,就是组合使用构造函数模式和原型模式。构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性,这种组合模式还支持向构造函数传递参数。实例对象都有一份实例属性的副本,同时又共享对方法的引用,最大限度地节省了内存。该模式是目前使用最广泛、认同度最高的一种创建自定义对象的方法

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("Nicoholas",29,"Software Engineer");
var person2 = new Person("hu",25,"Software Engineer");

person1.friends.push("Van");
alert(person1.friends);// "shelby","Court","Van";
alert(person2.friends);// "shelby","Court";
alert(person1.friends === person2.friends);//false
alert(person1.sayName === person2.sayName);//true

 动态原型模式

        动态原型模式将所有的信息都封装到了构造函数中,然后通过检查某个应该存在的方法是否有效,来决定是否初始化原型对象

优点:将原型对象合并到构造函数中,使得代码更加整齐,也减少了全局空间的污染

如果原型对象中包含多个语句,只需要检测其中一个语句即可

不要用字符字面量 重写原型,会切断现有实例和新原型之间的联系

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 friend = new Person("Nicholas",29,"Software Engineer");
friend.sayName();//'Nicholas'

 

猜你喜欢

转载自blog.csdn.net/qq_42265289/article/details/81254308