Js基础之创建对象的方法
一、单个对象
创建单个对象时,可以采用对象字面量{}或者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,将所有数据成员私有化
缺点:不可以添加成员
注意:同工厂模式一样,返回的对象和构造函数、构造函数的原型没有任何关系。
推荐阅读
-
从零学python系列之浅谈pickle模块封装和拆封数据对象的方法
-
PHP动态地创建属性和方法, 对象的复制, 对象的比较,加载指定的文件,自动加载类文件,命名空间,_PHP教程
-
Python学习---面向对象---类的定义、创建及对象方法的调用
-
浅谈JS对象添加getter与setter的5种方法
-
利用js创建模版的方法
-
Android开发之PopupWindow创建弹窗、对话框的方法详解
-
创建XMLHttpRequest对象的方法_PHP教程
-
SpringBoot系列教程JPA之基础环境搭建的方法
-
JS方法调用括号的问题探讨_基础知识
-
Node.js fs模块(文件模块)创建、删除目录(文件)读取写入文件流的方法