本文详细解析RequireJS中define函数的多种定义方式,包括简单值对、函数模块及依赖注入模式。重点阐述'use strict'严格模式的作用,以及define中name参数与require依赖名称必须保持一致的核心机制。通过源码逻辑分析,说明模块注册、路径加载及回调执行的完整流程,帮助开发者规范使用RequireJS进行模块化开发。
RequireJS模块定义基础
前言
模块概念区别于传统脚本文件,它通过定义独立作用域来避免全局命名空间污染。模块可显式声明依赖关系,并通过函数参数(即定义该模块的函数)注入依赖,无需引用全局变量。RequireJS的模块语法是模块模式的扩展,其优势在于无需全局引用其他模块。该语法支持并行加载多个模块,尽管加载顺序不确定,但依赖顺序最终正确。此外,由于不创建全局变量,同一页面可加载同一模块的不同版本。
严格模式的作用
在定义模块时,方法第一行添加“use strict”;的作用是什么?
“use strict”启用严格模式,使JavaScript在更严格的条件下运行。
- 消除JavaScript语法中不合理、不严谨之处,减少怪异行为;
- 消除代码运行中的不安全因素,保障代码执行安全;
- 提高编译器效率,增加运行速度;
- 为未来新版本的JavaScript做好铺垫。
define函数的五种定义方式
1. 简单的值对模块
将文件名作为name参数传入,若依赖该组件,则返回一个对象。
define({
name: "hehe",
age: "18"
});
2. 简单的函数模块
与上述类似,文件名作为默认name。差异在于,可提前执行返回值之外的代码。
define(function() {
return {
name: "hehe",
age: "18"
};
});
3. 依赖函数模块
define([
'angular',
'jsUtil',
'modules/meet/modules',
'modules/meet/services/Meet',
'modules/meet/services/MeetRemoteService'
],function(require) {
'use strict';
var module = angular.module('meet.services');
module.factory('MeetService', function(Meet, MeetRemoteService) {
var service = {
name: 'hehe',
age: '18'
};
return service;
});
});
与上述类似,关键在于依赖模块以返回值作为入参形式传入。若加载错误或未找到对应模块,入参为Undefined,需注意处理。
4. 返回函数模块
define([
'angular',
'jsUtil',
'modules/meet/modules',
'modules/meet/services/Meet',
'modules/meet/services/MeetRemoteService'
],function(require) {
'use strict';
var module = angular.module('meet.services');
module.factory('MeetService', function(Meet, MeetRemoteService) {
var service = {};
service.getWeekOfMeet = function(weekFlag, date) {
return MeetRemoteService.get(weekFlag, date).then(function(data) {
data.content = Meet.sortMeet(data.content);
return data;
});
}
return service;
});
});
与上述类似,此处返回的是函数。在依赖模块中将其作为函数对象调用即可,这实际上是一个简单的闭包。
5. 完整定义
define('sample3' ,['sample','sample1'],function (sample,sample1) {
var sample4 = require('sample4');
return function(){
alert(sample.name+':'+sample.sayhell());
}
});
这是完整定义形式,包含名称、依赖和回调,内部还有common形式的依赖对象引入。
define与require的命名机制
关于define函数的name和require函数的依赖名称之间的关系
define(name,[] , callback); 此name可省略,默认为文件名;也可自定义。一旦定义name,根据源代码可知,define函数内部将该name、依赖模块及回调函数作为对象存储在全局数组defQueue.push([name,deps,callback]);中。因此,该name即为组件注册的ID。
require([name , name2],callback); 系统首先全文检索path中是否存在对应路径,若无则将其作为路径拼接在baseUrl上异步加载JS文件。从源代码可见,var data = getScriptData(evt);返回的data.id 即为name,随后执行contex.completeLoad(node.id) 。其内部逻辑清晰:比较define中注册的name与此处得到的name,若相等则执行。因此,require和define的name必须保持一致!
总结
以上为本文全部内容,希望本文内容对大家的学习或工作有所帮助。如有疑问欢迎留言交流,感谢支持。