js 总结系列(二)对象的创建方式
一、Object构造函数
let person = new Object();
person.name="king";
person.say=function(){
console.log(this.name)
}
缺点:
- 写法繁琐,如果存在多个对象需要重复编写相同的属性或方法
- 无法给实例分类,因为得到的所有对象都是Object的实例。js给我们提供了几个原生的类型:Object、Array、RegExp、Date等,我们自己创建的对象虽然都是Object类型,但是有时候我们需要更加详细的类型。例如我们希望将
person
实例和animal
实例区分开,就需要我们自己定义Person
类型和Animal
类型。
二、对象字面量
let person = {
name: "king",
say: function() {
console.log(this.name)
}
}
缺点同上
三、工厂方式
为了解决具有相同属性的多个对象的创建,我们可以通过一个函数的形式来进行对象的创建。在这个函数中我们只需要通过传入形参的办法区分不同的属性或者方法。我们把这个用来创建对象的函数叫做工厂函数。所以这种方式也就称为工厂方式。
// 工厂函数
function createPerson(name) {
let person = new Object();
person.name = name;
person.say = function() {
console.log(this.name);
}
return person;
}
// 创建对象
let person1 = createPerson('king1');
let person2 = createPerson('king2');
通过上面的方式我们可以迅速地创建多个拥有say
方法的person实例,通过这样的方式我们就可以减少冗余的代码了。
缺点:工厂方式还是没能解决对象类型的问题
四、构造函数
我们通过js提供的原生类型进行对象创建的时候,往往是使用原生类型的构造函数进行对象的创建,那么我们在创建我们自定义类型的对象的时候,就需要我们有自定义的构造函数。其实构造函数就是普通的函数,只不过我们在写法上要跟普通的函数进行区分,一般来说构造函数首字母大写,普通函数首字母小写。我们在拥有了构造函数之后就可以像原生类型一样通过new
关键字进行对象的创建。
// 构造函数
function Person(name) {
this.name = name;
this.say = function() {
console.log(this.name);
}
}
function Animal() {}
// 创建对象
let person1 = new Person('king1');
let person2 = new Person('king2');
js中提供了instanceof
操作符来进行对象类型的判断,返回值是布尔值,true表示被判断的对象是当前构造函数的实例,false表示被判断的对象不是当前构造函数的实例。
person1 instanceof Person // true
person1 instanceof Animal // false
缺点:我们通过构造函数形式创建对象已经可以解决了Object构造函数创建方式的两个问题了,但是这里还有一个问题,其实有些内容我们是可以共用的,例如say
方法没有必要每个对象都有自己的say方法。
person1.say === person2.say // false
五、原型模式
为了解决上述问题,我们可以将对象的属性和方法添加到构造函数的远行对象上,这样我们创建的对象就可以通过原型链查找到相关的属性和方法。
// 构造函数
function Person() {}
Person.prototype.name = 'king';
Person.prototype.say = function() {
console.log(this.name);
}
Person.prototype.tools = {
hammer: 1,
axe: 1
}
// 创建对象
let person1 = new Person();
let person2 = new Person();
通过这种方式我们可以将多个对象的属性和方法共用
person1.say === person2.say // true
person1.tools === person2.tools // true
但是原型方式同样会有问题,如上例所示,修改person1的tools中的hammer值,同样会影响到person2的值。
person1.tools.hammer = 2;
console.log(person2.tools.hammer) // 2
所以我们应该将公用的属性和私有的属性进行区分,也就是组合构造函数和原型模式。
六、组合构造函数和原型模式
为了解决原型模式的问题,我们可以将私有的属性或方法放到构造函数中,将共有的属性或方法放到构造函数的原型对象上。
// 构造函数
function Person(name, tools) {
this.name = name;
this.tools = tools;
}
// 原型方法
Person.prototype.say = function() {
console.log(this.name);
}
通过混合使用构造函数方式和原型方式创建的对象基本上就可以解决我们遇到的问题了。