JavaScript设计模式:面向对象编程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript设计模式:面向对象编程相关的知识,希望对你有一定的参考价值。

javascript面向对象编程

  众所周知,JS作为一门脚本语言,由于其设计者在设计JS的时候,也仅仅用了很少的时间就完成了JS这门语言的创建,JS虽然拥有着脚本语言的优势,但是JS也存在着天生的缺陷。其中之一就是:“没有完整的面向对象和自定义类型支持”,这是因为JS本身没有很好的模块化。但事实上是,很多JS学习者或者使用者的共同点是:他们接触的第一门编程语言大都是C++或者Java这种老牌OOP语言,写代码时都是秉持着面向对象的思想,这在学习JS或者使用JS不免会感到有一些难受。

  那么JS可不可以实现面向对象编程,或者说,在某种程度上做到面向对象编程?答案是肯定的。

一、用对象收编函数与变量

  我们先看三个函数: 

 1 function fn1 () {
 2   // ...
 3 }
 4 
 5 function fn2 () {
 6   // ...
 7 }
 8 
 9 function fn3 () {
10   // ...
11 }

  这段代码有一个问题就在于:定义了三个全局函数,在一个项目里,这是不提倡的事实上也是不被允许的,创建全局函数或者变量,意味着在以后的代码里,这些函数或者变量就有与他人的代码产生冲突的可能。那么怎么解决这一类的问题呢?

  我们知道,对象可以拥有自己的属性与方法,并且在我们需要使用这些属性和方法的时候,通过点语法来使用。可不可以利用对象来收编这些函数或者变量呢?  看下面的代码:

 1 var obj = {
 2   fn1: function () {
 3     // ...
 4   }
 5   fn2: function () {
 6     // ...
 7   }
 8   fn3: function () {
 9     // ...
10   }
11 }

  通过创建一个这样的对象,我们就可以通过obj.fn1的方式,来调用对应的方法,并且这些方法是存在于obj对象上的。

  我们再看看下面的这种写法(与上面的写法其实是一种意思):

 1 var Obj = function () {}
 2 Obj.fn1 = function () {
 3   // ...
 4 }
 5 Obj.fn2 = function () {
 6   // ...
 7 }
 8 Obj.fn3 = function () {
 9   // ...
10 }

上面的方法存在着另外一个问题,当别人需要使用我们的对象方法的时候就有一些麻烦了,因为这个对象并不能被复制一份或者说我们通过 new 关键字

var test = new Obj() ,所创建的新对象test,并不拥有fn1,fn2,fn3这些方法。

要想解决这个问题,我们可以这么写:

 1 var Obj = function () {
 2   return {
 3     fn1: function () {
 4       // ...
 5     }
 6     fn2: function () {
 7       // ...
 8     }
 9     fn3:function () {
10       // ...
11     }
12   }
13 }

 这样写有什么作用呢?可以看出,每次调用该函数时,都会返回一个新对象,新对象拥有fn1,fn2,fn3这三个方法。这样,每个人在使用时就互不影响了。

1 var test = Obj()
2 test.fn1()

  我们虽然通过返回一个新对象在一定程度上解决了他人使用的问题,但这并不是真正意义上的类的创建方式(相信Java或者C++使用者深有体会),并且我们上面创建的对象test与Obj没有任何的关系,所以,我们再次换一种写法:

 1 var Obj = function () {
 2   this.fn1 = function () {
 3     // ...
 4   }
 5   this.fn1 = function () {
 6     // ...
 7   }
 8   this.fn1 = function () {
 9     // ...
10   }
11 }

 我们在这个函数内,使用了this关键字,像上面这样的一个对象Obj,我们就可以将其看成一个类了,拥有三个成员函数:fn1,fn2,fn3,既然是一个类,那么使用的时候就要通过new关键字来创建对象了:

1 var test = new Obj()
2 test.fn1()

  另一个问题出现了,每一个使用new关键字所创建出来的新对象,通拥有属于自己的一套方法,但事实上,这并不是必要的,这会造成内存不必要的消耗。

  怎么解决这个问题呢?不知道读者是否还记得JS中的每一个函数,都有一个prototype对象,我们称之为“原型”,原型上的属性和方法是new出来的对象所共享的,我们是否可以将公共的函数转移到prototype上呢?

 1 var Obj = function () {}
 2 Obj.prototype.fn1 = function () {
 3   // ...
 4 }
 5 Obj.prototype.fn2 = function () {
 6   // ...
 7 }
 8 Obj.prototype.fn3 = function () {
 9   // ...
10 }

这样我们以后通过new关键字创建的对象实例,所拥有的都是共同的方法,因为他们都要依赖prototype原型依次寻找,找到的方法都是同一个。

以上的这种方式,还有另一个写法:

 1 var Obj = function () {}
 2 Obj.prototype = {
 3   fn1: function () {
 4     // ...
 5   }
 6   fn2: function () {
 7     // ...
 8   }
 9   fn3: function () {
10     // ...
11   }
12 }

   需要注意的是,这两中方式并不能混用,因为如果在后面为对象的原型对象赋值为新对象的时候,它会覆盖掉之前对prototype对象赋值的写法。

  

以上是关于JavaScript设计模式:面向对象编程的主要内容,如果未能解决你的问题,请参考以下文章

javascript的面向对象的编程介绍书籍都有哪些

面向对象编程思想(前传)--你必须知道的javascript(转载)

JavaScript设计模式:面向对象编程

javaScript设计模式之面向对象编程(object-oriented programming,OOP)(二)

Scala的面向对象与函数编程

JavaScript的面向对象编程(OOP)——类