欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Js基础之创建对象的方法

程序员文章站 2022-03-17 13:15:56
...

一、单个对象

创建单个对象时,可以采用对象字面量{}或者new+object构造函数来创建;

var person1 = new Object(); //person1是由new+object构造函数创建
person1.name = 'ermiao';
person1.age = 18;    

var person2 = {       //person2是由对象字面量{}创建
    name:'Ermiao',
    age: 18
}

二、多个对象

创建多个对象时,相似的对象若每个都要单独创建,会产生重复的代码,因此采用以下方法:

1.工厂模式

工厂模式是抽象出创建对象过程中的重复步骤,并用一个函数封装起来的模式

function createPerson(name,age){
    var p = new Object();
    p.name = name;
    p.age = age;
    p.say = function(){
        alert(this.name);
    }
    return p
}

var person1 = createPerson('ermiao',18);

优点:解决了创建多个相似对象的问题

缺点:无法判断对象的类型

2.构造函数模式

除了采用自带的Object构造函数,还可以创建自定义构造函数

function Person(name,age){  //创建自定义的构造函数
    this.name = name;
    this.age = age;
    this.say = function(){
        alert(this.name);
    }
}
var person1 = new Person('ermiao',18);  //person1由new+自定义构造函数创建
var person2 = new Person('Ermiao',18);  //person2由new+自定义构造函数创建

对比工厂模式,(自定义)构造函数模式不用显示创建对象、不用返回对象、把对象的属性值都赋给了this。

在JavaScript中,构造函数和普通函数的唯一区别是调用方式不同。按照惯例,构造函数名的首字母应大写。

任何函数只要能够被new调用就叫构造函数不被new调用就是普通函数。如上例的Person函数,若不被new调用,就是普通函数,this指向全局变量window。

在用new+自定义构造函数生成实例时,经历了以下步骤:

  • 创建一个新对象
  • 将构造函数的作用域赋给新对象
  • 执行构造函数的代码(添加属性)
  • 返回新对象

优点:通过自定义构造函数创建的实例可以标识为特殊的类型(能够判断类型)。例如上例中person1和person2都是Person的实例,也都是Object的实例(继承)

缺点:被同一构造函数创建的多个对象之间没有联系。如上例person1和person2的say()函数是两个不同的函数,完成相同任务的函数不必要创建两遍并在执行前绑定在特定对象上。

3.原型模式

为了增加同一构造函数创建的多个对象之间的联系,每个函数都有一个prototype(原型)属性指向原型对象。原型对象包含特定类型的所有实例共享的属性和方法(如上例的say方法只在原型对象定义一次,并由person1和person2共享)

关于原型对象的内容请看:一文看懂原型链

var Person = function(){}; //原型模式不定义构造函数,只定义原型对象中的共享属性 

Person.prototype = {
    constructor: Person, //采用对象字面量给prototype赋值,一定要将constructor改成Person
    name:'ermiao',
    age:18,
    say:function(){
        alert(this.name);
    }
};

优点:能够使实例之间共享属性和方法

缺点:若所有属性都是共享不太方便,并且若共享属性是引用类型的,则能够同时更改可能导致错误

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

最常用的方法是组合使用构造函数和原型模式,由构造函数创建独有属性,由原型对象定义共享属性。

var Person = function(name,age){ //构造函数模式
    this.name = name;
    this.age = age;
}; 

//采用对象字面量给prototype赋值,一定要将constructor改成Person   
Person.prototype = {  //原型模式
    constructor: Person,
    say:function(){
        alert(this.name);
    }
};

优点:既能定义实例属性又能定义实例共享属性

缺点:要定义两次属性(构造函数,原型对象)

5.动态原型模式

该模式是在构造函数中初始化原型对象属性(必要情况下),只在初次调用构造函数时才执行。

var Person = function(name,age){
    this.name = name;
    this,age = age;
    if(typeOf this.say != 'function'){    //此处也可用instanceOf判断
        Person.prototype.say = function(){
            alert(this.name);
        };
    }
}

var person1 = new Person('ermiao',18);

person1.say(); //输出'ermiao'

注意:使用动态原型模式不能用对象字面量来定义原型属性,会改变原型的constructor属性(指向object)

优点:保留构造函数和原型模式的优点,又封装在一起

缺点:定义原型属性时不能用对象字面量

6.寄生构造函数模式

该模式除了使用new操作符调用函数,其他和工厂模式是一样的(效果一样,写法一样)

//工厂模式定义函数
var Person = function(name,age){  //区别1:函数名按构造函数规则写
    var p = new Object();
    p.name = name;
    p.age = age;
    p.say = function(
        alert(this.name);
    )
    return p
};
var person1 = new Person('ermiao',18);  //区别2:使用new操作符调用函数

注意:同工厂模式一样,返回的对象和构造函数、构造函数的原型没有任何关系。

当使用new操作符调用构造函数时,若构造函数中没有返回值(return),则默认返回创建的实例;若构造函数中有返回值,则以返回值优先

优点:只是看起来比工厂模式更像创建对象(但实质和工厂模式一样)

缺点:返回的对象和构造函数没关系,不能判断对象的特有类型,不建议使用该模式

7.稳妥构造函数模式

稳妥对象是指没有公共属性也不使用this的对象。

该模式不使用this和new,在函数中,只为返回对象绑定方法,不绑定数据,传入或内部定义的参数作为私有变量只能由返回对象的方法调用。(相当于c++中类的私有变量)

function Person(name,age){
    var p = new Object(); //创建返回对象
    //定义私有变量
    var para_name = name;
    var para_age = age;
    //定义返回对象的方法
    p.sayName = function(){
        alert(para_name);
    };
    p.sayAge = function(){
        alert(para_age);
    };
}

var person1 = Person('ermiao',18);

person1.sayName(); //输出'ermiao'
person1.sayAge(); //输出18
person1.name; //输出undefined

优点:比较安全,不使用this和new,将所有数据成员私有化

缺点:不可以添加成员

注意:同工厂模式一样,返回的对象和构造函数、构造函数的原型没有任何关系。

 

 

 

 

 

 

 

 

 

 

 

相关标签: js 对象