JavaScript的define函数

这是我参与更文挑战的第7天

AMD规范就是其中比较著名一个,全称是Asynchronous Module Definition,即异步模块加载机制。

从它的规范描述页面看,AMD很短也很简单,但它却完整描述了模块的定义,依赖关系,引用关系以及加载机制。

1.AMD是什么?

作为一个规范,只需定义其语法API,而不关心其实现。

AMD规范简单到只有一个API,define函数,语法如下:

define([module-name?], [array-of-dependencies?], [module-factory-or-object]);
复制代码
  • module-name: 模块标识,可以省略。

  • array-of-dependencies: 所依赖的模块,可以省略。

  • module-factory-or-object: 模块的实现或者一个JavaScript对象。

define函数AMD中的A:Asynchronous,我们也不难想到define函数具有的另外一个性质,异步性。当define函数执行时,

第一步:会异步的去调用第二个参数中列出的依赖模块,

第二步:当所有的模块被载入完成之后,

第三步:如果第三个参数是一个回调函数则执行,然后告诉系统模块可用,也就通知了依赖于自己的模块已经可以使用。

对于NodeJs这样的服务器端AMD,则模块载入无需阻塞服务器进程,同样提高了性能。

2.AMD示例:如何定义一个模块

define('alpha', ['require', 'exports', 'beta'], function (require, exports, beta) {
  exports.verb = function() {
      return beta.verb();
      //或者:return require(“beta”).verb();
  }
});
复制代码

代码说明:定义了一个alpha模块并且依赖于内置的require,exports模块以及外部的beta模块。可以看到,第三个参数是回调函数,可以直接使用依赖的模块,他们按依赖声明顺序作为参数提供给回调函数

  • require函数让你能够随时去依赖一个模块,即取得模块的引用,从而即使模块没有作为参数定义,也能够被使用;

  • exports是定义的alpha 模块的实体,在其上定义的任何属性和方法也就是alpha模块的属性和方法。通过exports.verb = …就是为alpha模块定义了一个verb方法。例子中是简单调用了模块beta的verb方法。

3.匿名模块

注意:define 方法允许你省略第一个参数,这样就定义了一个匿名模块,这时候模块文件的文件名就是模块标识

如果这个模块文件放在a.js中,那么a就是模块名。可以在依赖项中用”a”来依赖于这个匿名模块。这带来一个好处,就是模块是高度可重用的。你拿来一个匿名模块,随便放在一个位置就可以使用它,模块名就是它的文件路径。这也很好的符合了DRY(Don’t Repeat Yourself)原则。

define(['alpha'], function (alpha) {
  return {
    verb: function(){
      return alpha.verb() + 2;
    }
  };
});
复制代码

4.仅有一个参数的define

前面提到,define的前两个参数都是可以省略的。第三个参数有两种情况,

A.一个JavaScript对象

(1)一个包含方法具有功能的一个对象

(2)提供数据的数据对象(跟JSONP非常类似)

//我们命名未china.js的模块文件
define({
  provinces: [
    {
      name: ‘上海’,
      areas: [‘浦东新区’, ‘徐汇区’]
    },{
      name: ‘江苏’,
      cities: [‘南京’, ‘南通’]
    }
    //省略其他数据,请注意这个是一个数据文件
  ]
}); 
复制代码

假设这个文件名为china.js,那么如果某个模块需要这个数据,只需要(使用匿名模块规则):

define(['china'], function(china){
  //在这里使用中国省市数据
});
复制代码

通过这种方式,这个模块是真正高度可复用的,无论是用远程的,还是Copy到本地项目,都节约了开发时间和维护时间。

B.一个函数

如果参数是一个函数,其用途之一是快速开发实现。

define(function(){
  var p = require(‘china’);
  //使用china这个模块
});
复制代码

适用于较小型的应用,你无需提前关注自己需要什么模块,自己给谁用。在函数中,可以随时require自己需要的模块。

即你省略了模块名以及自己需要依赖的模块。这不意味着你无需依赖于其他模块,而是可以让你在需要的时候去require这些模块。

define方法在执行的时候,会调用函数的toString方法,并扫描其中的require调用,提前帮助你载入这些模块,载入完成之后再执行。这使得快速开发成为可能。需要注意的一点是,Opera不能很好的支持函数的toString方法,因此,在浏览器中它的适用性并不是很强。但如果你是通过build工具打包所有的 JavaScript文件,这将不是问题,构建工具会帮助你扫描require并强制载入依赖的模块。

5.总结

不是工作的需要,我想我不会接触到这个知识点,一直负责后端的代码,已经很久不涉及前端代码了。NodeJS也不是很了解,自己的习惯还是喜欢系统的学习,但是工作不允许你耽误时间,所以有时候就是使用Ctrl+C和Ctrl+V的调试成功就可以。

AMD 规范是JavaScript开发的一次重要尝试,它以简单而优雅的方式统一了JavaScript的模块定义和加载机制,并迅速得到很多框架的认可和采纳。这对开发人员来说是一个好消息,通过AMD我们降低了学习和使用各种框架的门槛,能够以一种统一的方式去定义和使用模块,提高开发效率,降低了应用维护成本。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享