seajs之define函数
本文介绍 seajs
的模块定义方式。
define(factory) 函数定义模块
在 seajs
中,使用 define
函数来定义一个模块,其接受 id
, dependencies
和一个工厂函数 factory
作为参数。其中,前两个参数可选。
1 |
|
id 参数
当前模块的唯一标识。该参数可选。如果没有指定,默认为模块所在文件的访问路径。如果指定的话, 必须是顶级或绝对标识(不能是相对标识)。
dependencies 参数
当前模块所依赖的模块,是一个由模块标识组成的数组。该参数可选。如果没有指定,模块加载器会从 factory.toString()
中解析出该数组。
注意:强烈推荐不要设定 id 和 dependencies 参数。 在开发阶段,模块加载器会自动获取这两个参数。部署上线时,则可以通过优化工具来提取这两个参数。
factory 参数
模块的工厂函数。模块初始化时,会调用且仅调用一次该工厂函数。factory
可以是函数, 也可以是对象、字符串等任意值,这时 module.exports
会直接设置为 factory
值。
factory
函数在调用时,会始终传入三个参数: require、exports 和 module
, 这三个参数在所有模块代码里可用。
1 |
|
require 函数
require
函数用来访问其他模块提供的 API。
1 |
|
require.async 异步加载函数
该方法可用来异步加载模块,并在加载完成后执行回调函数。
1 |
|
require.resolve 函数
使用 require()
的内部机制来解析并返回模块路径。该函数不会加载模块,只返回解析后的路径。
require.load 函数
该方法可用来异步加载脚本,并在加载完成后,执行指定的回调函数。开发插件时, 可以通过覆盖该方法来实现自定义的资源加载。
require.constructor 属性
有时候,我们需要给所有 require
参数对象添加一些公用属性或方法。这时, 使用 require.constructor
来实现会非常方便。
exports 对象
我们可以在 exports
对象上挂载对外的接口。
1 | // foo.js |
如上代码所示,我们定义了一个 foo.js
模块,并向外导出了一个 foo
方法。那么,我们可以这样在其他模块中使用她:
1 | define(function( require, exports , module ){ |
module 对象
我们也可以使用 module.exports
对象向外导出接口。
1 | // bar.js |
如上代码所示,我们在 bar.js
模块中导出了对象作为对外接口。我们在引用她试试:
1 | define(function( require, exports , module ){ |
module.id 属性
当前模块的唯一标识。 require(module.id) 必然返回此模块的 exports。
1 | define(function(require, exports, module) { |
module.dependencies 属性
module.dependencies
是一个数组,表示当前模块的依赖列表。该数组只读:模块加载完成后,修改该数组不会有任何效果。
module.exports 对象
exports
对象由模块系统创建,这不能满足开发者的所有需求, 有时候会希望 exports
是某个类的实例。 这时可用 module.exports
来实现:
1 |
|
注意,对 module.exports 的赋值需要同步执行,它不能放在回调函数里。 下面这样是不行的。
x.js
1 |
|
y.js
1 |
|
module.constructor 属性
有时候,我们需要给所有 module
参数对象添加一些公用属性或方法。在这种情况下, 使用 module.constructor
可以很好地满足需求。
extend.js
1 | // extend.js |
a.js
1 | // a.js |
exports 和 module 的区别
sea.js
的这部分实现,借鉴了 CommonJs
规范,即 node.js
中的模块实现。也就是说,exports
只是 module.exports
的一个引用,require
函数返回的永远是 module.exports
对象。所以对于如下操作是不对的:
1 |
|
注:不能直接对
exports
直接重新赋值,重新赋值后,exports
就不再指向module.exports
对象了,当你require
该模块时,其返回的永远都是{}
。