• Java程序猿JavaScript学习笔记(4——关闭/getter/setter)



    计划和完成这个例子中,音符的顺序如下:

    1. Java程序猿的JavaScript学习笔记(1——理念)
    2. Java程序猿的JavaScript学习笔记(2——属性复制和继承)
    3. Java程序猿的JavaScript学习笔记(3——this/call/apply)
    4. Java程序猿的JavaScript学习笔记(4——this/闭包/getter/setter)
    5. Java程序猿的JavaScript学习笔记(5——prototype)
    6. Java程序猿的JavaScript学习笔记(6——面向对象模拟)
    7. Java程序猿的JavaScript学习笔记(7——jQuery基本机制)
    8. Java程序猿的JavaScript学习笔记(8——jQuery选择器)
    9. Java程序猿的JavaScript学习笔记(9——jQuery工具方法)
    10. Java程序猿的JavaScript学习笔记(10——jQuery-在“类”层面扩展)
    11. Java程序猿的JavaScript学习笔记(11——jQuery-在“对象”层面扩展)
    12. Java程序猿的JavaScript学习笔记(12——jQuery-扩展选择器)
    13. Java程序猿的JavaScript学习笔记(13——jQuery UI)
    14. Java程序猿的JavaScript学习笔记(14——扩展jQuery UI)

    这是笔记的第4篇,聊聊闭包/getter/setter。看看JavaScript中的变量作用域和实现封装的方法。


    作者博客:http://blog.csdn.net/stationxp

    作者微博:http://weibo.com/liuhailong2008

    转载请取得作者允许



    1、闭包

    闭包是JavaScript一项简单有用的语言特性。通过闭包:
    弥补了函数没有public/private等訪问訪问权限控制符的缺陷。保护了函数内部变量的安全。


    使得函数对象在作为參数传递时,不只传递运算逻辑,同一时候也传递了相关变量。


    使得函数“类”的不同实例。独享自己的属性。
    以下逐个来看。

    1.1、保护私有变量

    1.1.1、原理

    闭包最基本的特性是:当函数作为返回值时,连同函数定义时的环境(包含函数外部,函数能够訪问到的变量)一起返回,确保这些变量不因其依附的对象销毁而被销毁。
    有点儿绕,详细什么意思呢?看以下的代码:
    // 代码段1
     function UiObject() {
         var childCount = 0; // 函数内部变量,  
         return 0;
     }
     
     var funcReturnValue = UiObject();  // 调用函数,返回0
     console.log(UiObject.childCount);   // 输出:undefined,因为函数调用完毕。内部变量已经被销毁
     
     childCount随着UiObject函数的调用结束而销毁,从还有一个角度看。保护了函数内部的变量。
     在这个基础上,假设我们有一种办法能够确保函数的内部变量不被销毁。并且提供方法对其訪问操作。也就实现了通过public方法訪问 private 变量。


     代码例如以下:
     // 代码段2
     function UiObject() {
         var childCount = 0; // 函数内部变量
         function getChildCount(){
             childCount = 6;
             return childCount;
         }
         return getChildCount;
     }
     var funcReturnFObject = UiObject();  // 调用函数,返回 getChildCount 函数,返回值是一个闭包
     console.log(funcReturnFObject());   // 输出:6
     以下我们就看看,假设利用闭包的这一特性实现对私有属性的保护。
     
     

     1.1.2、语法

     在代码段2的基础上改进,代码段3展示的代码。能够同一时候提供多个方法,对私有属性訪问。
     //代码段3
     function UiObject() {
         var childCount = 0; // 函数内部变量
         
         return {
             getChildCount : function (){
                 return childCount;
             },
             setChildCount : function (cnt){
                 childCount = cnt;
             }
         };
     }
     
     var o = UiObject();  // 调用函数,返回 getChildCount 函数,返回值是一个闭包
     o.setChildCount(6);
     console.log(o.getChildCount());   // 输出:6
     
     思考: 假设 var childCount = 0 ; 改为 this.childCount = 0; 呢?
     我们之前研究过this,“ this.childCount = 0; ”语句是将childCount附加为调用者的属性,this.childCount的将生命周期与调用者同样。

    这与闭包不冲突。
     
     代码段3还能够写成代码段4的形式。


     
     // 代码段4
     function UiObject() {
         var childCount =  0; // 函数内部变量
         this.setChildCount = function(cnt){
             childCount = cnt;
         };
         this.getChildCount = function(){
             return childCount;
         };
     }
     
     var ui = new  UiObject();          // 调用函数,返回retObj
     console.log(ui.childCount);       // 输出:undefined,因为函数调用完毕,局部变量已经被销毁
     ui.setChildCount(3);                  // 因为闭包的作用。ui仍然保存着变量childCount,并对其操作
     console.log(ui.getChildCount()); // 输出:3
     
     “this.setChildCount = function(cnt){       childCount = cnt;   };” 这个语句相当于在UiObject内部定义了函数并“传递”了给ui对象。相同产生了闭包。


     

    1.2、传递函数时。同一时候传递上下文

    通过上面的样例,我们已经看到了这点特性。
    在详细的应用场景中可对其大加利用。

    1.3、不同实例,独享自己的变量

    我们已经知道了。函数在传递过程中,会产生一个闭包。对于同一方法产生的闭包,是同样的,还是为每次传递创建了不同的拷贝呢?
    看以下的代码:
    //代码段5
     function UiObject() {
         var childCount = 0; // 函数内部变量
         
         return {
             getChildCount : function (){
                 return childCount;
             },
             setChildCount : function (cnt){
                 childCount = cnt;
             }
         };
     }
     
     var ui1 = UiObject();
     var ui2 = UiObject();
     
     ui1.setChildCount(1);
     ui2.setChildCount(2);
     
     console.log(ui1.getChildCount()); // output : 1
     console.log(ui2.getChildCount()); // output : 2
     
     每次生成闭包是不同的拷贝。
     
     思考:对照Java。加深理解。
     
     

    2、getter/setter


    JavaScript
     //代码段6
     var uiPanel ={
         _type  : 'Panel',
         _width : -1,
         _height: -1,
         
         get type(){ return this._type;},
         
         get width(){ return this._width; },
         set width(v){this._width = v;},
         
         get height(){ return this._height; },
         set height(v){this._height = v;}
     };
     
    uiPanel.type = 'TextField';          // does not work
    console.log('type:'+uiPanel.type); // ouput :         type:Panel
     
     uiPanel.width = 800;                 //
     console.log(''+uiPanel.width); // ouput :         800

    语法上越发有面向对象的范儿了。
    除了在定义时通过set/setkeyword控制属性的读写权限。还能够在执行期通过 Object.defineProperty()函数动态加入属性。并提供更精细的控制。


    代码例如以下(下面代码均未经实验):
    var o = {};
    Object.defineProperty(o,'propName',{
                value:1,  //属性的值,也能够通过   get:function(){retun x。}的方法设定
                writeable:true,//能否够通过o.propName  = newValue ; 的方法设置属性的值
                enumerable:false,//能否够通过被枚举
                configurable:true//能否够通过defineProperty配置
        });
    另外,另一系列API能够完毕对属性的配置、检測。例如以下:
    Object.getOwnPropertyDescriptor{{x:1},"x"}
    Object.keys(obj);    // 获得对象上全部可枚举的“实例属性”
    Object.getOwnPropertyNames(obj) ;//获得对象上全部的“实例属性”
    obj.hasOwnProperty(‘id’); //仅仅要该对象obj拥有属性id, 不管id是否可枚举,都返回true


    3、小结

    当大多数人已经习惯了面向对象的思维和方法,语言就要从特性方面予以满足。这不合理,也不美。但世界就是如此不完美。

    JavsScript天生丽质。非要把她改造成机甲战士,那以后谁来负责倾国倾城呢?

    ECMAScript 5不是革命性创新,也不是救命稻草这个世界本来能够更好的。




    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    Robot Framework-资源文件的使用方法(7)
    Robot Framework-用户关键字的使用方法(6)
    robotframework 新建UI自动化测试用例实例一(2)
    robotframework--登录接口,post传递多个参数、及获取content中指定属性的值(5)
    robotframework基础知识(2)
    win7如何打开防火墙某个端口的tcp连接
    外观模式
    享元模式
    代理模式
    模板模式
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4612445.html
Copyright © 2020-2023  润新知