JavaScript创建对象的常用方式总结
传统的创建对象的方式
1、创建Object的实例
var person = new Object();
person.name = "xiaoming";
person.age = 18;
person.showName = function() {
console.log((this.name)); //xiaoming
};
person.showName();
2、对象字面量形式创建单个对象
var person = {
name : "xiaoming",
age : 18,
showName:function() {
console.log(person.name); // xiaoming
}
};
person.showName();
创建对象的五种设计模式
1、工厂模式
function createPerson(n,s,a) {
var o = new Object();
o.name = n;
o.sex = s;
o.age = a;
o.sayName = function() {
console.log(this.name)
};
return o;
}
var person1 = createPerson('xiaoming', 'boy','8');
console.log(person1); //{name: "xiaoming", sex: "boy", sayName: ƒ}
person1.sayName() //xiaoming
优点:可以无限次调用,每次都会返回设定了属性和方法的对象。(简单封装,可以传参)
缺点:解决了创建多个相似对象的问题,但是没有解决对象识别问题,即不能知道一个对象的类型。(检测不出是什么的实例)
2、构造函数模式
function Person(n,s,a) {
this.name = n;
this.sex = s;
this.age = a;
this.sayName = function() {
console.log(this.name) //xiaoming
}
}
var person1 = new Person('xiaoming','男','18');
console.log(person1); //Person {name: "xiaoming", sex: "男", age: "18", sayName: ƒ}
person1.sayName();
没有显示的创建对象,使用new来调用这个构造函数,使用new后会自动执行如下操作:
①创建一个新对象;
②将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
③执行构造函数中的代码(为这个新对象添加属性);
④返回新对象。
缺点:每个方法都要在每个实例上重新创建一遍。(每创建一个对象就有开辟存放方法的空间)
3、原型模式
function Person() {
}
Person.prototype.name = 'xiaoming';
Person.prototype.sex = '男';
Person.prototype.age = '18';
Person.prototype.sayName = function() {
console.log(this.name)
};
var person1 = new Person();
person1.sayName(); // xiaoming
缺点:不能传参,属性共享
将信息直接添加到原型对象上。使用原型的好处是可以让所有的实例对象共享它所包含的属性和方法,不必在构造函数中定义对象实例信息,而是可以将这些信息直接添加到原型对象中。
4、组合使用构造函数模式和原型模式
function Person(name) {
this.name = name;
this.friends = ['Jack', 'Merry']
}
Person.prototype.sayName = function() {
console.log(this.name)
};
var person1 = new Person();
var person2 = new Person();
console.log(person1.friends); //["Jack", "Merry"]
console.log(person2.friends); // ["Jack", "Merry"]
console.log(person1.friends === person2.friends) //false
优点:能传参,属性放构造方法中,方法放原型中
缺点:属性和方法分开放置
使用此模式可以让每个实例都会有自己的一份实例属性副本,但同时又共享着对方法的引用,这样的话,即使实例属性修改引用类型的值,也不会影响其他实例的属性值了。还支持向构造函数传递参数,可谓是集两种模式的优点。
5、动态原型模式
function Person(name, sex) {
// 属性
this.name = name;
this.sex = sex;
// 方法
if(typeof this.sayName !== 'function') {
Person.prototype.sayName = function() {
console.log(this.name) //xiaoming
}
}
}
var person1 = new Person('xiaoming', '男');
person1.sayName();
只有在sayName方法不存在的时候,才会将它添加到原型中。这段代码只会初次调用构造函数的时候才会执行。
动态原型模式把所有信息都封装在了构造函数中,而通过在构造函数中初始化原型,又保持了同时使用构造函数和原型的优点。
可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。