方式 1:字面量(直接量)创建对象
形式 :主要通过 var obj = { ... };语句进行创建。
优点 :1)创建方式简单,快捷,清晰,适用于创建单个或非常少量或属性方法非常没有规律的对象。
2)创建和添加属性及属性值可以在一个语句完成。
缺点 :1)创建效率低,不适用于程序化地生成多个对象。
2)生成的对象不具有相应的对象类型,只是一个个单独的对象。
方式 2: new Object()创建对象
形式 :主要通过 var obj = new Object();语句先创建一个对象(此时完全等价于 var obj = {}; 语句 ),然后再对这个对象进行添加相应的属性和属性值。
优点 :相对来说更直观看出是在创建一个对象。
缺点 :1)创建过程麻烦,创建和添加属性及属性值要分两个步骤完成。
2)创建效率低,不适用于程序化地生成多个对象。
3)生成的对象不具有相应的对象类型,只是一个个单独的对象。
方式 3:工厂模式(工厂方法、工厂方式)创建对象
形式 :通过调用同一个函数生成多个对象
function createPerson (name,age,sex) {//工厂方式创建对象
var p = {}; //方式1
p.name = name;
p.age = age;
p.sex = sex;
return p;
// var p = { //方式2
// name : name;
// age : age;
// sex : sex;
// }
// return p;
// return { //方式3(ES6 新增,此时需考虑兼容性)
// name, // 此时相当于 name = name; 以下依次类推
// age,
// sex
// }
}
var p1 = createPerson("张三",120,"男");
var p2 = createPerson("李四",56,"女");
优点 :1)可以通过调用同一个函数生成多个对象,提高代码的效率。
2)可以使用一些ES6新增的较为简洁的书写方式写在封装函数里,但是需考虑兼容性。
缺点 :1)当只定义单个对象时书写过于麻烦,累赘。
2)生成的对象不具有相应的对象类型,只是一个个单独的对象。
方式 4 :通过构造函数创建对象
形式 :使用var obj = new 类型名(属性值);和调用同一个函数(此时这个函数叫构造函数)方式创建对象
function Person (name,age,sex) {
this.name = name; // 如果调用时用的new方式,则this指代将来要创建的那个对象(此时这个函数叫构造函数),如果不是用new方式而当作一个普通函数使用时,则this指的是window
this.age = age;
this.sex = sex;
// return this; //new时自动的返回this,可以省略
当做构造函数的时候,默认返回的是this;当显示的去返回一个新的对象,则外面拿到的就是这个新的对象,如果返回的不是一个对象,则返回给外面的还是this
// return { //(ES6新增)但是此时即使在调用的时用的new方式虽然返回值使得对象内容相同,但此时对象不是一个类型,与工厂方式效果一样,故不能这样用。
// name,
// age,
// sex
// }
}
var p1 = new Person("张三",120,"男"); //构造函数方式创建对象
var p2 = new Person("李四",56,"女");
优点 :1)可以通过调用同一个函数生成多个对象,提高代码的效率。
2)生成的对象具有相应的对象类型,不仅仅只是生成一个个单独的对象。
缺点 :1)当只定义单个对象时书写过于麻烦,累赘。
2)不可以使用一些ES6新增的较为简洁的书写方式写在封装函数里,不然会造成返回的对象不具有相应的对象类型,而只是一个个单独的对象。
方式 5:通过原型创建对象
形式 :使用var obj = new 类型名(属性值);和调用同一个函数(此时这个函数叫构造函数)方式创建对象,但是属性及方法的添加在原型中。
function Person1 (name,age) {
}
Person1.prototype = {
construcor : Person1,//使原型对象重新指向Person1
this.name : name, //原型有属性共享的缺点
this.age : age,
this.add : function () {}, //原型实现方法共享的优点
console.log(this.name + "在说"); //this根据调用方式不同this指代的对象不同
}
var p1 = new Person1();
优点 :方法共享
缺点 :属性共享
方式 6:动态原型创建对象
形式 :通过保留构造函数和原型的优点且避免他们各自的缺点来实现。
function Person1 (name,age) { //构造函数实现属性不共享的优点
this.name = name;
this.age = age;
this.add = function () {};
if (!Person1.prototype.speak) {//动态原型 //if语句用来避免重复性的生成相同的函数造成内存浪费
Person1.prototype.speak = function () { //原型实现方法共享的优点
console.log(this.name + "在说");
}
} //方法是可以写在构造函数外面的,但是为了实现封装的整体性加到了构造函数里面。
}
var p = new Person1();
优点 :保留构造函数和原型的优点且避免他们各自的缺点。
缺点 :对于具有多个方法时,if语句有点繁琐。
方式 7:动态原型演变方式创建对象
形式 :在动态原型上完善。
function Person1 (option) { //动态原型演变方式1
// this.name = option.name; //添加属性方式1,属性名和属性值的添加在构造函数中进行
// this.age = option.age;
// this.add = function () {};
// for(var index in option){ //添加属性方式2,适用于属性名及属性值不修改的情况
// this[index] = option[index];
// }
this._init(option);//动态原型演变方式2,把属性的添加整合到原型中
}
Person1.prototype = {
_init : function (option){//动态原型演变方式2
for(var index in option){
this[index] = option[index];
}
},
constructor : Person1, //让对象的constructor重新指向Person1
speak : function () {
console.log(this.name + "在说");
}
}
var pp1 = new Person1({name : "张三",age : 30});
var pp2 = new Person1({name : "李四",age : 40});
pp1.speak();//张三在说
pp2.speak();//李四在说
console.log(pp1.speak === pp2.speak); //true
console.log(pp1.add == pp2.add); //false
优点 :(1)保留构造函数和原型的优点且避免他们各自的缺点。
(2)把对象的初始化都整合到原型中生成,方便操作,并且避免了if语句的繁琐。