本文分上下两部分,上部讲基本模式(basic patterns):完全暴露法,下划线标记法和使用闭包;下部讲高级模式(Advanced Patterns),如何实现静态方法和属性,常量还有其他一些知识点。 封装是面向对象语言很基本也是很有用的特性,虽然javascript也可以称的上是面向对象语言,但他对封装的支持并不是很好,不像其他语言,只要使用private、protected就可以实现。但这并不是说就没有办法了,下面我就介绍下如何在javascript中实现封装。 一、基本模式(basic patterns),主要包括三种方式:完全暴露法,下划线标记法和使用闭包。(闭包是个很重要,也是很难的概念,有兴趣的朋友可以去网上找资料,我博客里也转载了别人的文章)。 这里我们以book类作为例子,需要创建和初始化book类。 复制代码 代码如下: // Book(isbn, title, author) var theHobbit = new Book("0-395-07122-4", "The Hobbit", "J. R. R. Tolkien"); theHobbit.display(); // Outputs the data by creating and populating an HTML element.
1.完全暴露法: 创建book类可以用最传统的构造函数方式, 复制代码 代码如下: var Book = function(isbn, title, author) { if(!this.checkIsbn(isbn)) throw new Error("Book: Invalid ISBN."); this.isbn = isbn; //代码中 || 的作用是 如果title无值,则会把"No title specified"赋给 this.title。这种方式很好用,大家可以在自己的代码中使用。 this.title = title || "No title specified"; this.author = author || "No author specified"; } Book.prototype = { //验证isbn函数 checkIsbn: function(isbn) { ... }, //获取isbn getIsbn: function() { return this.isbn; }, //设置isbn setIsbn: function(isbn) { if(!this.checkIsbn(isbn)) throw new Error("Book: Invalid ISBN."); this.isbn = isbn; }, //获取title getTitle: function() { return this.title; }, //设置title setTitle: function(title) { this.title = title || "No title specified"; }, //获取作者 getAuthor: function() { return this.author; }, //设置作者 setAuthor: function(author) { this.author = author || "No author specified"; }, //显示函数 display: function() { ... } };
代码有点多,我在这里简单讲解下。javascript中创建类和c#,java有点不同,c#,java会把所有方法和属性包在一个类文件里面,比如说 复制代码 代码如下: public class book() { private string isbn; public string ISBN { set { this.isbn=value; } get { return this.isbn; } } ... private bool CheckIsbn(string isdn) { ...... } ...... public void Display() { ...... } }
其实就是在所有想实现私有的属性或者方法前面加了下划线_,没别的操作。这种方法并没有实现真正的私有化,theHobbit._isbn = "978-0261103283";这样操作照样成功,这种方式最大的意义在于告诉类的使用者,作者本意上想暴露哪些对象,不想暴露哪些。但是使用者是否按照作者的想法去做,作者是控制不了的。 那有没有办法实现真正的私有化呢,答案是有的,就是利用闭包。 3.使用闭包: javascript之所以能实现真正的封装,是和他特有的函数作用域,函数支持内部函数,还有闭包分不开的。大家可以去网上搜集相关知识加深理解。 下面首先说的就是函数作用域,在javascript中如果在一个函数内部定义了一个变量,那么函数外部是没有办法访问的。其实在javascript中实现私有属性或者方法就是利用了它这一特殊属性。例子: 复制代码 代码如下: function foo() { var a = 10; function bar() { a *= 2; } bar(); return a; }
在上面的例子中函数foo在内部定义了变量a和方法bar,在foo外部是无法访问到a和bar的,但是因为a和bar都定义在foo内部,但bar是可以访问到a的。那么有没有办法能在foo外部访问到bar呢,答案是有的,就是使用闭包。 复制代码 代码如下: function foo() { var a = 10; function bar() { a *= 2; return a; } return bar; } var baz = foo(); // baz is now a reference to function bar. baz(); // returns 20. baz(); // returns 40. baz(); // returns 80. var blat = foo(); // blat is another reference to bar. blat(); // returns 20, because a new copy of a is being used.