• 《JS权威指南学习总结--8.5 作为命名空间的函数》


    内容要点:
        函数作用域的概念:在函数中声明的变量在整个函数体内都是可见的(包括在嵌套的函数中),在函数的外部是不可见的。不在任何函数内声明的变量是全局变量,在整个JS程序中都是可见的。

        在JS中无法声明只在一个代码块内可见的变量的。(在客户端JS中这种说法不完全正确,比如,在有些JS的扩展中就可以使用let来声明语句块内的变量)

        基于这个原因,我们常常简单地定义一个函数用做临时的命名空间,在这个命名空间内定义的变量是都不会污染到全局命名空间。

        比如,假设你写了一段JS模块代码,这段代码将要用在不同的JS程序中(对于客户端JS来讲通常是用在各种各样的网页中)。和大多数代码一样,假定这段代码定义了一个用以存储中间计算结果的变量。这样问题就来了,当模块代码放到不同的程序中运行时,你无法得知这个变量是否已经创建了,如果已经存在这个变量,那么将会和代码产生冲突。

        解决方法是:将代码放入一个函数内,然后调用这个函数。这样全局变量就变成了函数内的局部变量。

    一.定义匿名函数并立即在单个表达式中调用

         (function(){

             //模块代码

          }());  //结束函数定义并立即调用它

         这种定义匿名函数并立即在单个表达式中调用它的写法非常常见,已经成为一种惯用法了。

         下例中,展示了这种命名空间技术。它定义了一个返回extend()函数的匿名函数,此匿名函数中的代码检测了是否出现一个众所周知的IE bug,如果出现了这个bug,就返回一个带补丁的函数版本。此外,这个匿名函数命名空间用来隐藏一组属性名。

          例:

          //特定场景下返回带补丁的extend()版本

          //定义一个扩展函数,用来将第二个以及后续参数复制至第一个参数

          //如果o的属性拥有一个不可枚举的同名属性,则for/in循环不会枚举对象o的可枚举属性,也就是说,将不会正确地处理诸如toString的属性,除非我们显式检测它

          var extend = (function(){ //将这个函数的返回值赋值给extend

                //在修复它之前,首先检查是否存在bug

                for( var p in {toString:null} ){  

                        //如果代码执行到这里,那么for/in循环会正确工作并返回

                        //一个简单版本的extend()函数

                      return function extend(o){

                             for(var i=1;i<arguments.length;i++){

                                  var source = arguments[i];

                                   for( var prop in source ) o[prop] =source[prop];

                                }

                        return o;

                     }; 

              }

                //如果代码执行到这里,说明for/in循环不会枚举测试对象的toString属性

                //因此返回另一个版本的extend()函数,这个函数显式测试

               //Object.prototype中的不可枚举属性

               return function patched_extend(o){

                     for( var i=1;i<arguments.length;i++ ){

                         var source=arguments[i];

                         //复制所有的可枚举属性

                        for( var prop in source ) o[prop] = source[prop];

                        //现在检查特殊属性

                       for( var j=0;j<protoprops.length;j++ ){

                           prop = protoprops[j];

                           if( source.hasOwnProperty(prop)) o[prop] = source[prop];

                            }

                         }

                     return o;

                    };

                  var protoprops = ["toString","valueOf","constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumrable","toLocaleString"];

             }());

            var h ={x:1,y:2,z:3};
             var s = extend(h);
             console.log(s);   //Object { x=1,  y=2,  z=3}
             console.log(s.x); //1

  • 相关阅读:
    置换加密算法
    堆和优先队列的应用
    定时发送邮件小程序
    Hibernate的缓存
    Spring中使用JDBC
    Spring AOP(创建切面)
    处理不可中断阻塞
    SQL语句实例说明
    spring_声明式事务
    Flex_includeIn属性的作用
  • 原文地址:https://www.cnblogs.com/hanxuming/p/5822487.html
Copyright © 2020-2023  润新知