本文已参与「新人创作礼」活动,一起开启掘金创作之路。
创建对象的方式
构造函数法
//构造函数法
var obj=new Object();
obj.name="echo";
obj.age=18;
对象字面量法
//对象字面量法
var obj={
name:"echo",
age:18
}
这两种方式都可以用来创建对象,但是当我们需要创建较多的对象时,如果全部采用上述方法进行对象的创建的话,就需要编写很多重复的代码,造成代码冗余。我们就可以将上述创建对象的方式封装在一个函数里,当我们要创建对象的时候就去调用这个函数,这里用到的就是工厂模式。
工厂模式
如上所说,我们可以将创建对象的代码封装在一个函数里,并将需要定义的属性值以参数的方式传递给这个函数。
function createPerson(name,age,height){
var person=new Object();
person.name=name;
person.age=age;
person.height=height;
return person;
}
var p=createperson("echo",18,1.68);
构造函数模式
工厂模式解决了代码冗余的问题,但是使用工厂模式我们没有办法获得关于这个对象更具体地类型上述代码中p类型为createPerson这种。所以又引入了构造函数的概念
构造函数
构造函数与普通函数本质上并没有什么区别,只不过构造函数是通过new关键字进行调用的,可以这么说,通过new关键字调用的函数都是构造函数,习惯上,我们会将构造函数的第一个字母大写用来跟其他的普通函数做区分。
function Person(name, age) {
this.name = name;
this.age = age;
}
var p = new Person("echo", 18);
console.log(p.constructor.name);//Person
以上就是通过构造函数模式创建对象的过程,首先我们可以先了解一下new一个构造函数的过程中发生了什么
- 创建一个空对象
- 绑定原型
- 将构造函数的作用域赋给新对象(绑定this)
- 执行构造函数中的代码(为这个对象添加属性)
- 返回新对象 每个通过构造函数new出来的实例对象内部都有一个constructor属性,这个属性指向它的构造函数。所以我们可以通过打印实例对象.contructor.name来获取这个对象的构造函数的名称,这样我们就可以区分由不同的构造函数创建出的实例对象了,这也是构造函数模式胜过工厂模式的地方。
构造函数的缺点
每创建一个构造函数的实例对象都会为其开辟一块内存空间,如果实例对象内包含函数就又会为其开辟一块空间,且不同实例对象内部同名函数是不相同的,也就是说我们创建了两个实例对象这两个实例对象内部的同名函数是分别开辟了两块空间进行存储的。
function Person(name, age) {
this.name = name;
this.age = age;
this.eating = function () {
console.log(this.name);
}
}
var person1 = new Person("echo", 18);
var person2 = new Person("lan", 22);
console.log(person1.eating == person2.eating); //false
上述打印可以说明两个实例对象的同名函数是不相等的,其在内存中的表示为
但是呢,同一个构造函数创建出的两个实例对象下的同名函数所执行的任务是相同的,完全没有必要为其开辟两块空间,要解决这个问题我们可以把构造函数内部的方法移到构造函数的外部,如下:
function Person(name, age) {
this.name = name;
this.age = age;
this.eating = eating;
}
function eating() {
console.log(this.name);
}
var person1 = new Person("echo", 18);
var person2 = new Person("lan", 22);
person1.eating();
这样虽然可以解决上述问题,但是我们原本是希望只有这个构造函数的实例对象才可以访问该构造函数内的方法的,但是我们将其内部的方法放在了全局作用域,这个都可以访问到这个函数了,而且如果构造函数内部有多个函数的话,我们就需要在全局作用域定义多个函数,那我们这个构造函数毫无封装性可言了。针对这一问题,由引入了原型模式
原型模式
原型的好处就在于其实例对象可以共享原型上的属性和方法,因此我们可以把构造函数中的方法放到构造函数的原型对象上。
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.eating = function () {
console.log(this.name);
}
var person1 = new Person("echo", 18);
var person2 = new Person("lan", 22);
person1.eating();