[javascript]模块化&命名污染—from 编程精解

  最近看了编程精解里面的模块化一章,很受启发。

  /****************/

  在开发的实际过程中,根据页面或者逻辑布局,js代码可以按照功能划分为若干个区块:数据交互、表单验证、页面布局等等模块

  为了提高开发效率和后期代码维护,很自然的应该将几十个js函数划分为模块,利于调试和后续修改。但写出几十个函数的时候,命名自然就出现问题了,想不出别的函数名或者干脆两个函数重名了,这种因为重复声明而导致的bug称为命名污染,这在大型项目中很常见。

  提到模块开发,最容易想到的是通过js文件来分模块存储和调用代码。而文件存储的弊病是:比如首页加载了3,4个js文件(应该不算多),不同文件里面的全局变量,包括函数和变量,怎么保证不存在命名冲突,当然,通过给变量名和函数名前加前缀是一个很笨但是很奏效的办法,有没有什么办法能够从最基础上避免这种命名污染、同时能够实现代码模块化呢?

  

  1.通过模块对象来实现。

    举一个书中的例子,要做一个月份翻译器,把1翻译为一月。对于新手来讲很可能是这样的:

      

var names = [‘一‘,‘二‘,‘三‘,‘四‘,‘五‘,‘六‘,‘七‘,‘八‘,‘九‘,‘十‘,‘十一‘,‘十二‘];
function getMonthName(num){
    return names[num-1]+‘月‘;
};
function getMonthNum(str){
    for(var i in names){
        if( str == (names[i]+‘月‘)){
            return i+1;
        }
    }
};

  这里面的names和getMonthName,getMonthNum的生存域都是顶级的,所以如果其他文件或者js代码中声明了名字为names的变量,就会导致程序异常(getMonthName,getMonthNum这么长的名字一般很少重复)。

  在一个后台管理网站里面,需要写的函数可能有:表单验证、图片轮播组件、dom加载、从某input里面读数据再拼成json、hover效果、弹出层....如果这些功能或者插件都是直接声明全局函数或全局变量,想命名就会想哭的。

  

  所以这时候,应该想到利用函数闭包来避免产生作用域命名污染,上面代码的最简修改就是

  

//匿名函数声明并直接调用
//names作为局部变量出现 不会污染顶级作用域,外部无法访问
//通过为顶级作用域的window对象绑定函数的方式,对外暴露接口
(function(){
    var names = [‘一‘,‘二‘,‘三‘,‘四‘,‘五‘,‘六‘,‘七‘,‘八‘,‘九‘,‘十‘,‘十一‘,‘十二‘];
    window.getMonthName = function getMonthName(num){
        return names[num-1]+‘月‘;
    };
    window.getMonthNum = function getMonthNum(str){
        for(var i in names){
            if( str == (names[i]+‘月‘)){
                return i+1;
            }
        }
    };
})();

  这种方法也有不好的地方,我们总不能把所有的函数接口都绑定到window对象的属性当中,那和直接在代码里声明函数没区别。

  所以,再一步优化就是做模块对象,很简单的优化,把函数绑定到模块对象上,通过访问模块对象的属性来调用功能:

  

  

var monthTranslator = (function(){
    var names = [‘一‘,‘二‘,‘三‘,‘四‘,‘五‘,‘六‘,‘七‘,‘八‘,‘九‘,‘十‘,‘十一‘,‘十二‘];
    return {
        getMonthName:function(num){
            return names[num-1]+‘月‘;
        },
        getMonthNum:function(str){
            for(var i in names){
                if( str == (names[i]+‘月‘)){
                    return i+1;
                }
            }
        }
    };
})();

  上面的函数调用时,直接使用 monthTranslator.getMonthName(1);  就可以了。当然也可以把names作为模块对象的属性出现,这就看功能设计了。

  /*************/

  上面说的这些就是js代码的模块化,这个见仁见智,有的人可能觉得你这种写法有什么用处呢,“我自己想个命名前缀不就得了,有必要写这么麻烦的函数么”

  但是我觉得,良好的代码风格是一个程序员的优良品德。对人对己,都是极好的。

  

  最近喜欢用brackets...小轻快,不错不错

时间: 2024-09-29 08:40:30

[javascript]模块化&命名污染—from 编程精解的相关文章

[已读]JavaScript编程精解

译者汤姆大叔,应该很多人都知道,他写了一系列的关于闭包与作用域理解的文章,但是由于创建了一些我不理解的新名词,我不爱看. <JavaScript编程精解>算是买得比较早的一本书,那会大肆搜罗js基础书籍,这本应该是在我看完<javascript高级程序设计(第二版)>之后,紧接着看的,金玉在前,所以,原谅我对它的印象不够好,另外,我没有耐心按照书中生态圈的例子一点一点敲代码,对很多人提到的这本书的趣味性也就没有体会. 关于内容,首先,它不适合没有基础的读者看,会有一点难看懂.第二,

JavaScript 编程精解 中文第三版 翻译完成

原书:Eloquent JavaScript 3rd edition 译者:飞龙 自豪地采用谷歌翻译 部分参考了<JavaScript 编程精解(第 2 版)> 在线阅读 PDF格式 EPUB格式 MOBI格式 代码仓库 赞助我 协议 CC BY-NC-SA 4.0 原文地址:https://www.cnblogs.com/wizardforcel/p/9125631.html

变量、作用域和内存问题总结[JavaScript]

JavaScript的基本类型值和引用类型值具有以下特点: 1.基本类型值在内存中占据固定的大小,因此被保存在栈内存中: 2.引用类型值是对象,保存在堆内存中: 3.从变量向另一个变量复制基本类型的值,会创建这个值的一个副本: 4.包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针: 5.从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终指向用一个对象: 6.确定一个值是哪种基本类型可以使用typeof操作符,而确定一个值是哪种引用类型可以使用ins

[转]android学习----基础UI编程(四)

CheckBox 的使用 RadioButton 的使用 12. CheckBox 的使用 1)通过只含有一个CheckBox的实例来学习CheckBox的使用 示例代码 ① 创建新工程② 在string.xml 中添加字符串 <?xml version="1.0" encoding="utf-8"?><resources><string name="app_name">Ex_Ctrl_4</string

[转]android学习----基础UI编程(六)

相簿浏览 Gallery 文件搜索引擎FileSearch 17. Gallery 与 衍生BaseAdapter 容器 Gallery控件,即Android的图片库控件. 需要定义一个BaseAdaper的子类(eg.ImageAdapter)来操作控制图片资源,然后在主类中通过Gallery.setAdapter(new ImageAdapter(this));来使用这个控制类. 示例代码 本例中 ImageView 和 Gallery 控件相互协作 . ① 新建项目 ② 定义layout

[转]android学习----基础UI编程(二)

7. TextView 和 EditView 共舞 预达到效果:在EditText中输入同时TextView进行输出 //前提:在main.xml中添加EditText 和 TextView控件 核心代码示例: public class EX_Ctrl_1 extends Activity {    private TextView mTextView01;    private EditText mEditText01;    // Called when the activity is fi

[转]android学习----基础UI编程(七)

自动完成输入框 AutoCompleteTextView 多内容自动完成输入框 19. AutoCompleteTextView 自动完成输入框 智能输入框 AutoCompleteTextView 1. 简介 一个可编辑的文本视图显示自动完成建议当用户键入.建议列表显示在一个下拉菜单,用户可以从中选择一项,以完成输入.建议列表是从一个数据适配器获取的数据. 2. 重要方法 clearListSelection():清除选中的列表项 dismissDropDown():如果存在关闭下拉菜单 ge

[转]android学习----基础UI编程(八)

模拟/数字/线程小时钟设计 动态输入日期与时间 日期设置/时间设置对话框 21. 模拟/数字/线程小时钟设计 AnalogClock 与DigitalClock 的原理,以及线程时钟的实现 . 示例代码 ① 新建工程② 修改man.xml 布局,添加一个AnalogClock.一个DigitalClock.一个TextView<TextView  //这个TextView 用来显示线程时钟    android:id="@+id/TextView_showTime"    and

[转]android学习----基础UI编程(一)

1 通过 DisplayMetrics 类获取屏幕宽高 示例代码: package zyp.Activity; import android.app.Activity;import android.os.Bundle;import android.widget.*;import android.util.*; public class Test extends Activity {    //Called when the activity is first created. private T