引言
如果我们现在希望创建一系列的对象:比如Animal对象,Person对象,采取什么样的方式比较好呢。本文列举常见的几种方向并详细分析它们的优劣性。
字面量创建
这个方法是最好想到,也是最常见的。不过效率极低,创建同样的对象时,用户需要编写重复的代码。
let p1 = {
age:18,
name:'张'
}
let p2 = {
age:19,
name:'李'
}
let p3 = {
age:20,
name:'王'
}
工厂模式创建对象
工厂模式其实是一种常见的设计模式,通常我们会有一个工厂方法,通过该工厂方法我们可以产生想要的对象。
//代码1
function createPerson(name,age,height,address){
var p = {} //创建一个对象
p.name = name
p.age = age
p.height = height
p.address = address
p.eating = function(){
console.log(this.name+"在吃东西");
}
p.running = function(){
console.log(this.name+"在跑步");
}
return p
}
var p1 = createPerson("张三",18,1.88,"广州市") //p类型
var p2 = createPerson("李四",19,1.69,"上海市") //p类型
var p3 = createPerson("王五",20,1.79,"北京市") //p类型
console.log(typeof p3); //Object(缺点,类型问题,只能打印Object,而不能确定是哪个Object)
工厂模式的缺点
如果读者运行代码1后,会发现typeof打印的是Object。工厂模式的缺点在于类型问题,只能打印Object,而不能确定是哪个Object。
使用构造函数进行创建
构造函数是什么
构造函数也称之为构造器(constructor),通常是我们在创建对象时会调用的函数。在其他面向的编程语言里面,构造函数是存在于类中的一个方法,称之为构造方法。但是JavaScript中的构造函数有点不太一样。
一个普通的函数被使用new操作符来调用了,那么这个函数就称之为是一个构造函数了。
如果一个函数被使用new操作符调用了,那么它会执行如下操作:
- 在内存中创建一个新的对象(空对象)
- 这个对象内部的[[prototype]]属性会被赋值为该构造函数的prototype属性
- 构造函数内部的this,会指向创建出来的新对象
- 执行函数的内部代码(函数体代码)
- 如果构造函数没有返回非空对象,则返回创建出来的新对象
构造函数的案例
注意构造函数的命名要符合驼峰命名法,如果只有一个单词那么首字母大写!
function Person(name,age,height,address){
this.name = name;
this.age = age;
this.height = height
this.address = address //属性没有问题
this.eating = function(){ //放到p1.eating p1.runing里面 调用p2会创建p2.eating....
console.log(this.name+"再吃东西"); //函数在内存中开辟了两个空间
} //从代码执行角度来看没有毛病,但是没有必要给每个对象都创建一个新的函数对象
//万一创建100个对象,这样子很浪费空间。
this.runing = function(){
console.log(this.name+"在跑步");
}
}
var p1 = new Person("张三",18,1.88,"广州市")
var p2 = new Person("李四",19,1.69,"长沙市")
console.log(p1);
构造函数的缺点
(在这里我要强调一下,对象中的函数叫做方法,防止大家看到函数和方法两个概念会弄混)
缺点:我们需要为每个对象的方法去创建一个函数对象实例,在上面的代码也体现出来了。这很好理解,我们每次创建一个对象,对象中都会有一个方法,但是这个方法是没有返回值的,也就是说它会一直在内存中存放着,如果用户想要创建一个对象,那么这100个对象里都会存放着100个方法。对象的属性我们无需顾虑,因为每次实例一个新的对象属性大多都不会相同,然而方法就必须考虑了(比如复用性等问题)。
解决缺点:使用原型来解决,我的下一篇文章也会重点介绍原型。对象的原型与函数的原型
Person.prototype.xxx = function(){
}
本人掘金文章https://juejin.cn/post/7109016539520565285/