JS创建对象常见的方式有很多种,接下来我们对这几种创建方式以及它们的优缺点进行一 一对比。
第一种,使用new关键字。
var person = new Object();
person.username = "张三"; //先创建对象,而后为对象添加属性username
person.age = 25; //先创建对象,而后为对象添加属性age
person.show = function(){
console.log(person.age ,person.username);
} //为对象添加一个方法。
person.show(); //方法调用
使用new关键字创建js对象这种方式语法简单。但是,这种方式有着明显的缺陷,它的复用性很差。当我们需要多个person对象的时候,我们就不得不将以上的代码重复多次,导致代码臃肿。在开发中不推荐使用这种方式。
第二种,使用字面量。
所谓的JS字面量,是js中对象的另一种表示形式。我们先上一个实例感受一下。
var person = {
username:"张三",
age:25,
show:function () {
console.log(this.age,this.username);
}};
person.show();
字面量的语法格式为使用一对大括号包围对象内容,字段名/方法名与字段值/方法体之间使用冒号分割。这种创建形式的优点是与JSON格式很像,易于与JSON格式转换。缺点与上一种形式类似,当我们需要大量对象的时候,代码臃肿。故使用场景也有局限性。为了解决上述代码臃肿与不可重用等诸多缺陷,JS有提供了如下语法。
第三种,工厂方法。
function person(username,age) {
let o = new Object();
o.username = username;
o.age = age;
o.show = function () {
console.log(this.age,this.username);
}
return o;
}
var someone = person("张三",25);
someone.show();
console.log(someone instanceof person);//false
console.log(typeof someone );//输出值为object
此种方式与下方的构造方法方式类似,可以有效解决复用问题,但是不能通过instanceof来判断变量类型。那么,有没有能够明确表示出对象类型的方式呢?
第四种,使用构造方法。
function Person(username,age) {
this.username = username;
this.age = age;
this.show = function () {
console.log(this.age,this.username);
}
}
let someone = new Person("张三",25);
someone.show();
console.log( typeof someone);//输出为object
console.log(someone instanceof Person);//true
此种方法有效的解决了复用性问题,也可以通过instanceof来鉴定出具体类型。但是在实际使用中仍有问题。show方法是每个对象实例独有的,当需要创建大量对象的时候,show方法将会创建很多份。了解面向对象编程思想的都知道,在面向对象编程中,字段是一个对象实例独有的,用来标识该对象实例独有的特征。而方法用来标识通用功能,这种功能的理想实现方式是多个对象实例共享同一个。那么有没有理想的方式,让字段实例独有,方法实例间共享呢?我们接着往下看。
第五种、原型模式
function person(){}
person.prototype.username = "张三";
person.prototype.age = 25;
person.prototype.show = function () {
console.log(this.username,this.age);
}
var someone =new person();
var someone2 =new person();
someone.show();
console.log(typeof someone); //object
console.log(someone instanceof person); //true
console.log(someone2.show === someone.show);//true
如上所示,原型模式在通过instanceof正确识别的基础上,方法实例只保存了一份。有效的解决了冗余问题。但是又有新问题了,由于原型链对字段的操作,导致字段也被所有实例所共享。数据会由此混乱。如何避免这种问题呢?
第六种、原型与构造混合模式
为了让字段各实例独有,而方法共享可以使用如下创建方式。
function Person(username,age){
this.username = username;
this.age = age;
}
Person.prototype.show = function () {
console.log(this.username,this.age);
}
此种方式已经解决上述提出个各种问题。但是,还能否优化呢?
第七种、原型与构造混合模式增强
上述方式中,字段定义与方法定义是分离的,优化的写法如下
function Person(username,age){
this.username = username;
this.age = age;
if(typeof this.show != 'function' ){
Person.prototype.show = function () {
console.log(this.username,this.age);
}
}
}
第八种、原型与工程混合模式
在有些场景下,我们希望字段是对外不可见的, 也就是说外部无法直接访问与修改字段值,可以使用如下的方式。
function Person(username,age){
let object = new Object();
object.username = username;
object.age = age;
object.show = function () {
console.log(object.username,object.age);
}
return object;
}
let person = Person("张三",25);
person.show();