zoukankan      html  css  js  c++  java
  • javascript 封装

    javascript既是一门函数式语言,也是一门面向对象的语言,但是要想在javascript中实现类似于java中的private变量可不是一件显而易见的事。你需要借助它的函数式特性:闭包。 

    下面的例子演示了如何构建一个javascript对象,没有任何的隐藏和封装。 

    Javascript代码  收藏代码
    1. /** 
    2.  * 此demo演示了如何在javascript中实现面向对象语言中的信息封装和隐藏。由于javascript不像java那样在语言层面 
    3.  * 提供了很好的封装支持,因此需要借助一些模式。 
    4.  */  
    5.   
    6.   
    7. Book = function(isbn, title, author) {  
    8.     if (!isbn) throw new Error('isbn is invalid');  
    9.     this.isbn = isbn;  
    10.     this.title = title;  
    11.     this.author = author;  
    12. };  
    13.   
    14. Book.prototype = {  
    15.     display: function() {  
    16.         if (!this.isbn) throw new Error('invalid book');  
    17.         console.log('title :' + this.title + '    author: ' + this.author + '    isbn: ' + this.isbn);  
    18.     }  
    19. };  
    20.   
    21. var book = new Book('0981531652','Actors In Scala''Philipp Haller / Frank Sommers');  
    22. book.display();  
    23.   
    24. //可以直接的改变book中的成员,使得book不再是合法的book  
    25.   
    26. book.isbn = null;  
    27.   
    28. book.display();  



    由于没有类似于java中的private关键字,人们发明了“命名规范”来约定所有以下划线'_'开头的变量和方法名都是“私有“的,不应该(注意,是不应该,不是不能)被外部直接调用。 

    Javascript代码  收藏代码
    1. /** 
    2.  * 在很多javascript库中,通常约定以下划线 '_'开头的变量或者方法名为私有的变量和方法,不应该直接被外部调用 
    3.  */  
    4.   
    5. Book = function(isbn,title,author) {  
    6.     if (!isbn) throw new Error('invalid isbn');  
    7.     this._isbn =isbn;  
    8.     this._title = title;  
    9.     this._author = author;  
    10. };  
    11.   
    12.   
    13. Book.prototype = {  
    14.     display: function() {  
    15.         if (!this._isbn) throw new Error('invalid book');  
    16.         console.log('title :' + this.title + '    author: ' + this.author + '    isbn: ' + this.isbn);  
    17.     }  
    18. };  
    19.   
    20. var book = new Book('0981531652','Actors In Scala''Philipp Haller / Frank Sommers');  
    21. book.display();  
    22. //Book的开发者: oh, _isbn是一个似有变量,你不应该改变直接改变它。  
    23. //调用者: 我不是故意的,代码调用层次太深了,我也不知道哪里导致一不小心被设置了。  
    24. book._isbn = null;  
    25. book.display();  



    这种办法在每一个程序员都比较自觉的情况下可以发挥效用,但是如果哪个粗心的程序员一不小心。。。 

    我们需要一种真正的封装!闭包可以做到这一点!什么叫闭包?根据维基百科的定义,一个闭包就是包含自由变量的代码块,这些自由变量定义在代码块所处的上下文中,而不是定义在代码块内部或者全局上下文中。 

    Javascript代码  收藏代码
    1. /** 
    2.  * 通过javascrit中的closure来实现真正的私有变量。 
    3.  */  
    4.   
    5. Book = function(isbn, title, author) {  
    6.     var _isbn, _title, _author;//局部变量  
    7.       
    8.     //局部方法  
    9.     function checkIsbn(isbn) {  
    10.         if (!isbn) throw new Error('cannot set invalid isbn');  
    11.     };  
    12.       
    13.     this.getTitle = function() {  
    14.         return _title;  
    15.     };  
    16.       
    17.     this.setTitle = function(title) {  
    18.         _title = title;  
    19.     };  
    20.       
    21.     this.getIsbn = function() {  
    22.         return _isbn;  
    23.     };  
    24.       
    25.     this.setIsbn = function(isbn) {  
    26.         checkIsbn(isbn);  
    27.         _isbn = isbn;  
    28.     };  
    29.       
    30.     this.getAuthor = function() {  
    31.         return _author;  
    32.     };  
    33.       
    34.     this.setAuthor = function(author) {  
    35.         _author = author;  
    36.     };  
    37.       
    38.     this.setTitle(title);  
    39.     this.setIsbn(isbn);  
    40.     this.setAuthor(author);  
    41. };  
    42.   
    43. Book.prototype = {  
    44.     display: function() {  
    45.         //这里我们不需要在检验isbn是否合法,因为每一次对isbn的更改都必须通过setIsbn的检查  
    46.         console.log('title :' + this.getTitle() + '    author: ' + this.getAuthor() + '    isbn: ' + this.getIsbn());  
    47.     }  
    48. };  
    49.   
    50. var book = new Book('0981531652','Actors In Scala''Philipp Haller / Frank Sommers');  
    51. try {  
    52.     book.setIsbn(null);  
    53. }catch(e) {  
    54.     console.log(e.message);  
    55. }  
    56.   
    57. book.display();  



    在上述例子中,_isbn是Book的构造函数中定义的局部变量,它只在构造函数体内有效;在构造函数中也定义了一个checkIsbn()方法,同样,它也只可以在Book的构造函数体内被调用。getIsbn()引用了_isbn这个局部变量,因此它构成了一个闭包,同时getIsbn()又是Book实例的一个方法,因此可以被外部所调用,同时外部调用者也只能通过getIsbn()来获得_isbn的值。这就实现了真正的隐藏。getIsbn()这个方法既可以访问局部变量,又可以被外部调用,称为对象的特权方法。 

    但是实现真正的隐藏是需要付出代价的: 

    1. 首先每一个特权方法(例如isbn的getter和setter)存在于每一个实例中,可能会造成内存占用过多 
    2. 在存在继承的情况下,子类无法直接服用父类的方法和成员变量,因为javascript使用的是prototype的继承。 

    在实际中,只有在要求非常严格的封装的情况下才会使用例三的方法,而大部分情况都可以使用命名约定的办法。

  • 相关阅读:
    functools.partial偏函数
    python之路——模块和包
    异常
    递归函数
    内置函数和匿名函数
    列表推导式和生成器表达式
    迭代器和生成器
    Parentheses Balance
    poj1363 Rails
    hud1237 简单计算器
  • 原文地址:https://www.cnblogs.com/taoze/p/2394226.html
Copyright © 2011-2022 走看看