起因 一般来讲,模块是一个独立的JS文件。模块文件可以包含一个类定义、一组相关类、一个实用函数库或者一些待执行的代码。 模块化的目标是支持大规模的程序开发,处理分散源中代码的组装,并且能让代码正确运行,哪怕包含了不需要的模块代码,也可以正确执行代码。 理想状态下,所有模块都不应当定义超过一个全局标识。 模块函数 一旦将模块代码封装进一个函数中,就需要一些方法导出公用API,以便在模块函数外部调用它们。下面有几种方式导出公用API: 首先创建一个命名空间 复制代码 代码如下: // 创建一个全局变量用来存放与学校相关的模块 var school; // 创建school命名空间 if(!school) school = {}; 1. 利用构造函数 复制代码 代码如下: // 返回Student构造函数来导出公共API school.Student = (function() { function Student() { } // ...... 定义Student的原型对象和私有属性和方法 ........ return Student; // 返回Student构造方法导出公共API })(); 2. 返回命名空间对象 如果模块API包括多个单元,则它可以返回命名空间对象 复制代码 代码如下: // 为school添加students模块 school.students = (function() { // 这里定义了很多类如课程类/成绩类, 使用局部变量和函数 function Subject() { /* ... */ } function Grade() { /* ... */ } // 通过返回命名空间对象将API导出 return { Subject: Subject, Grade: Grade }; })(); 3. 通过关键字new调用 另外一种类似类似技术:把模块函数当做构造函数,通过new来调用。把它们(公共API)赋值给this属性来将其导出 复制代码 代码如下: school.students = (new function() { // ..... 这里省略了代码 ...... // 将API导到this对象中 this.Subject = Subject; this.Grade = Grade; // 注意,这里没有返回值 }()); // 括号写在里面。这里是创建新实例,new后面应紧跟构造函数的调用而不是表达式 4. 已定义命名空间对象 作为一种替代方案,如果已经定义了全局命名空间对象,通过模块函数可以直接设置那个对象的属性。 复制代码 代码如下: // 如果已经定义了命名空间对象 var school; // 创建school命名空间 if(!school) school = {}; school.students = {}; // student命名空间已经定义 (function(students) { // ..... 这里省略了代码 ...... // 将公共API导到上面定义的命名空间中 students.Subject = Subject; students.Grade = Grade; // 这里也不需要返回值 })(school.students); 为此,导出公共API的方式已经讲完。 |
|
来自: ThinkTank_引擎 > 《命名空间》