最新资讯当前位置:星鸿娱乐 > 最新资讯 > >

星鸿娱乐平台javascript设计模式 封装和信息隐藏(

  

[封装,信息隐藏]javascript设计模式 封装和信息隐藏(上)

  本文分上下两部分,上部讲基本模式(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()  
{  
......

  
}  
}  

  
javascript也可以用这种方式,但是推荐使用我上面使用的把属性定义到类定义函数(或者叫构造函数),方法定义到prototype对象中,这种做法性能要好些,至于原因大家可以去google。

  
  上面的js代码想实现的功能是,定义一个book类,类里面包括三个私有变量(或者叫属性)isbn,title,author,一个私有方法checkIsbn,几个公有方法getIsdn,setIsdn,...display。想法是好的,但是现实是残酷的,其实那些私有属性或者方法根本一点都不私有。比如说,theHobbit.isbn = '978-0261103283';你可以用这种方式为isbn赋值,不会报错而且绝对成功。原因就是javascript没有private方式去实现对特定对象的私有化。此外这种实现方式在使用时也会造成困惑,到底类的创建者想暴露哪些属性和方法呢?下面介绍第一种改进办法,下划线标记法。

  
  2.下划线标记法:  
代码如下:

  
var Book = function(isbn, title, author) {  
  // Constructor code.

  
  this.setIsbn(isbn);  
  this.setTitle(title);  
  this.setAuthor(author);  
}  
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;  
  },  
  ...

  
  //显示函数  
  display: function() {  
  ...

  
  }  
};  

  
其实就是在所有想实现私有的属性或者方法前面加了下划线_,没别的操作。这种方法并没有实现真正的私有化,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.

  

  
这就是在前面提到的javascript函数支持内部函数。内部函数bar可以访问私有变量a,函数foo又把内部函数bar抛出给baz,baz就可以访问到内部变量a了,这就实现了闭包。大家一看也就明白了,这样其实就实现了私有变量和方法。回到我们前面的book例子,实现如下:  
代码如下:
  
var Book = function(newIsbn, newTitle, newAuthor) {  
  // implements Publication  
  // Private attributes.

  
  var isbn, title, author;  
  // Private method.

  
  function checkIsbn(isbn) {  
    ...

  
  }  
  // Privileged methods.

  
  this.getIsbn = function() {  
    return isbn;  
  };  
  this.setIsbn = function(newIsbn) {  
    if(!checkIsbn(newIsbn)) throw new Error('Book: Invalid ISBN.');  
    isbn = newIsbn;  
  };  
  this.getTitle = function() {  
    return title;  
  };  
  this.setTitle = function(newTitle) {  
    title = newTitle || 'No title specified';  
  };  
  this.getAuthor = function() {  
    return author;  
  };  
  this.setAuthor = function(newAuthor) {  
    author = newAuthor || 'No author specified';  
  };  
  // Constructor code.

  
  this.setIsbn(newIsbn);  
  this.setTitle(newTitle);  
  this.setAuthor(newAuthor);  
};  
// Public, non-privileged methods.

  
Book.prototype = {  
  display: function() {  
    ...

  
  }  
};  

  
上述代码就实现了 isbn, title, author和checkIsbn的私有化,外部是决定不能直接访问到的。如需访问 isbn, title, author只能通过对象级的方法getTitle,setTitle...。比如要给isbn赋值,只能用theHobbit.setIsbn = '978-0261103283';,如果你还用theHobbit._isbn = '978-0261103283';,对不起要报错了。

  
  
 好了,今天的内容就讲到这里了,希望对大家有帮助。

  
作者:下一站永远  
  

(责任编辑:admin)

上一篇:星鸿娱乐平台js关于字符长度限制的问题示例探讨

下一篇:jquery动态增加删减表格行特效

推荐内容

客户服务热线

010-400-12345

在线客服