视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
JavaScript面向对象-使用工厂方法和构造函数方法创建对象
2020-11-27 20:26:17 责编:小采
文档
 在上一篇文章中我们介绍了JavaScript简单对象的创建方法,简单js对象的最大问题是由于没有类的约束,无法实现对象的重复利用,并且没有一种约定,在操作时会带来问题。所以人们从设计模式中借用了一种工厂模式来创建JavaScript对象。

使用工厂方法创建JavaScript对象

工厂方法的的思路是在一个函数中创建一个对象,然后为这个对象设置相应的属性和方法,最后将这个对象返回。通过函数来封装,以特定的接口创建对象。下面是一个以工厂方法创建person对象的例子:

function createPerson(name,age){
 var o = new Object();
 o.name = name;
 o.age = age;
 o.say = function(){
 alert(this.name + "," + this.age);
 }
 return o;
}
// 实例化p1和p2对象
var p1 = createPerson("Leon",22);
var p2 = createPerson("Ada",20);
 
//调用p1和p2对象的say()方法
p1.say();
p2.say();

使用工厂方法虽然有效的解决了类的问题,但是依然存在另外一个问题。我们无法检测对象p1和p2的数据类型。我们使用typeof仅仅只能检测出对象是一个Object类型:

console.info(typeof p1); // 控制台
输出:Object

如果我们想要使用instanceof来判断对象的类型,那么p1 instanceof ,instanceof后面要填写什么类型呢?我们并不知道。

使用构造函数创建JavaScript对象

由于工厂方法不能确定对象的具体类型,所以人们又提出了一种新的创建JavaScript对象的方法——构造函数方法。在JavaScript中构造函数可以用来创建特定类型的对象,例如Object和Array这些js原生构造函数,在运行时会自动出现在执行环境中。我们也可以自定义构造函数,从而定义自定义类型的属性和方法。

使用构造函数来创建类和基于工厂的方式来创建类的方法相似,最大的区别是函数的名称就是类的名称。通常按照编程规范的约定,类的第一个字母大写。使用构造函数创建类时,在函数内部通过this关键字来完成属性的定义。

// 使用构造函数方式来创建Person类
function Person(name,age){
 this.name = name;
 this.age = age;
 this.say = function(){
 console.info(this.name + "," + this.age);
 }
}
// 通过new关键字来创建对象
var p1 = new Person("Leon",22);
var p2 = new Person("Ada",20);
// 调用对象的方法
p1.say();
p1.say();

如上面的代码所示,在完成类的创建之后,我们可以通过new关键字来实例化对象。

使用构造函数的方式很好的解决了检测对象类型的问题,我们可以通过instanceof关键字来判断对象是不是Person类型:

console.info(p1 instanceof Person); //控制台显示:true 
console.info(p2 instanceof Person); //控制台显示:true

另外,我们还可以通过constructor关键字来查看对象的构造函数是否是Person类型:

console.info(p1.constructor == Person); //控制台显示:true 
console.info(p2.constructor == Person); //控制台显示:true

或者直接打印出p1和p2的构造函数来进行比较:

console.info(p1.constructor);
console.info(p2.constructor);

使用构造函数方法给我们所带来的问题是每一个对象中都会存在一个方法的拷贝,如果对象的方法很多的话,就会占用大量的内存空间。

在一些高级的编译型的面向对象编程语言(如Java)中,对象的方法是在运行时动态在栈区产生的,它们不会占用内存。而在Javascript中,使用构造函数方法创建的对象,对象中的每一个方法都是类方法的一个拷贝,如果对象中存在大量的方法,就会占用大量的内存空间。

我们可以将类的方法放到全局变量中来定义,这样可以让类中的方法指向同一个函数。代码如下:

// 使用构造函数方式来创建Person类
function Person(name,age){
 this.name = name;
 this.age = age;
 // 此时的类方法是一个全局方法的引用
 this.say = say;
}
//将方法设置为全局的方法
function say(){
 alert(this.name + "," + this.age);
}

通过将类的方法设置为全局方法,可以解决对象中的方法占用内存空间的问题,此时,通过构造函数创建的所有对象中的方法都指向同一个全局函数。

但是如果将所有的方法都设置为全局函数,这些函数都可以被window调用,此时就破坏了对象的封装性,而且如果某个对象有大量的方法,就会导致代码中有大量的全局函数,这样也不利于我们的开发。

为了解决构造函数方法存在这些缺陷,我们就要使用原型来创建对象,下一篇文章我们将介绍使用原型来创建JavaScript对象。

下载本文
显示全文
专题