【Seajs源码分析】2. 工具方法1
Sea.js:
var seajs = global.seajs = {
// The current version of Sea.js being used
version: "@VERSION"
} var data = seajs.data = {}
代码定义了一个seajs变量并暴露给全局,变量现在只有一个值就是版本号变量
另外定义了一个data变量,后面会用到
util-lang.js
/**
* util-lang.js - The minimal language enhancement
*/ function isType(type) {
return function(obj) {
return {}.toString.call(obj) == "[object " + type + "]"
}
} var isObject = isType("Object")
var isString = isType("String")
var isArray = Array.isArray || isType("Array")
var isFunction = isType("Function")
var isUndefined = isType("Undefined") var _cid = 0
function cid() {
return _cid++
}
这里用一个函数来判断对象类型,这里有一个演变过程比较有意思,如果有兴趣可以参考下玉伯的github博客
cid方法用来产生一个唯一的ID,后面会用到
util-events.js
/**
* util-events.js - The minimal events support
*/ var events = data.events = {} // Bind event
seajs.on = function(name, callback) {
var list = events[name] || (events[name] = [])
list.push(callback)
return seajs
} // Remove event. If `callback` is undefined, remove all callbacks for the
// event. If `event` and `callback` are both undefined, remove all callbacks
// for all events
seajs.off = function(name, callback) {
// Remove *all* events
if (!(name || callback)) {
events = data.events = {}
return seajs
} var list = events[name]
if (list) {
if (callback) {
for (var i = list.length - 1; i >= 0; i--) {
if (list[i] === callback) {
list.splice(i, 1)
}
}
}
else {
delete events[name]
}
} return seajs
} // Emit event, firing all bound callbacks. Callbacks receive the same
// arguments as `emit` does, apart from the event name
var emit = seajs.emit = function(name, data) {
var list = events[name], fn if (list) {
// Copy callback lists to prevent modification
list = list.slice() // Execute event callbacks
while ((fn = list.shift())) {
fn(data)
}
} return seajs
}
一个事件处理机制,on用来注册事件,为指定事件数组添加回调函数,off用来移除事件,如果没有指定事件名和回调函数,删除所有事件的回调函数,如果没有指定回调函数,则删除该事件的所有回调函数,emit用来触发事件以及事件绑定的函数
util-path.js
/**
* util-path.js - The utilities for operating path such as id, uri
*/ var DIRNAME_RE = /[^?#]*\// var DOT_RE = /\/\.\//g
var DOUBLE_DOT_RE = /\/[^/]+\/\.\.\//
var DOUBLE_SLASH_RE = /([^:/])\/\//g // Extract the directory portion of a path
// dirname("a/b/c.js?t=123#xx/zz") ==> "a/b/"
// ref: http://jsperf.com/regex-vs-split/2
function dirname(path) {
return path.match(DIRNAME_RE)[0]
} // Canonicalize a path
// realpath("http://test.com/a//./b/../c") ==> "http://test.com/a/c"
function realpath(path) {
// /a/b/./c/./d ==> /a/b/c/d
path = path.replace(DOT_RE, "/") // a/b/c/../../d ==> a/b/../d ==> a/d
while (path.match(DOUBLE_DOT_RE)) {
path = path.replace(DOUBLE_DOT_RE, "/")
} // a//b/c ==> a/b/c
path = path.replace(DOUBLE_SLASH_RE, "$1/") return path
} // Normalize an id
// normalize("path/to/a") ==> "path/to/a.js"
// NOTICE: substring is faster than negative slice and RegExp
function normalize(path) {
var last = path.length - 1
var lastC = path.charAt(last) // If the uri ends with `#`, just return it without '#'
if (lastC === "#") {
return path.substring(0, last)
} return (path.substring(last - 2) === ".js" ||
path.indexOf("?") > 0 ||
path.substring(last - 3) === ".css" ||
lastC === "/") ? path : path + ".js"
} var PATHS_RE = /^([^/:]+)(\/.+)$/
var VARS_RE = /{([^{]+)}/g function parseAlias(id) {
var alias = data.alias
return alias && isString(alias[id]) ? alias[id] : id
} function parsePaths(id) {
var paths = data.paths
var m if (paths && (m = id.match(PATHS_RE)) && isString(paths[m[1]])) {
id = paths[m[1]] + m[2]
} return id
} function parseVars(id) {
var vars = data.vars if (vars && id.indexOf("{") > -1) {
id = id.replace(VARS_RE, function(m, key) {
return isString(vars[key]) ? vars[key] : m
})
} return id
} function parseMap(uri) {
var map = data.map
var ret = uri if (map) {
for (var i = 0, len = map.length; i < len; i++) {
var rule = map[i] ret = isFunction(rule) ?
(rule(uri) || uri) :
uri.replace(rule[0], rule[1]) // Only apply the first matched rule
if (ret !== uri) break
}
} return ret
} var ABSOLUTE_RE = /^\/\/.|:\//
var ROOT_DIR_RE = /^.*?\/\/.*?\// function addBase(id, refUri) {
var ret
var first = id.charAt(0) // Absolute
if (ABSOLUTE_RE.test(id)) {
ret = id
}
// Relative
else if (first === ".") {
ret = realpath((refUri ? dirname(refUri) : data.cwd) + id)
}
// Root
else if (first === "/") {
var m = data.cwd.match(ROOT_DIR_RE)
ret = m ? m[0] + id.substring(1) : id
}
// Top-level
else {
ret = data.base + id
} // Add default protocol when uri begins with "//"
if (ret.indexOf("//") === 0) {
ret = location.protocol + ret
} return ret
} function id2Uri(id, refUri) {
if (!id) return "" id = parseAlias(id)
id = parsePaths(id)
id = parseVars(id)
id = normalize(id) var uri = addBase(id, refUri)
uri = parseMap(uri) return uri
} var doc = document
var cwd = dirname(doc.URL)
var scripts = doc.scripts // Recommend to add `seajsnode` id for the `sea.js` script element
var loaderScript = doc.getElementById("seajsnode") ||
scripts[scripts.length - 1] // When `sea.js` is inline, set loaderDir to current working directory
var loaderDir = dirname(getScriptAbsoluteSrc(loaderScript) || cwd) function getScriptAbsoluteSrc(node) {
return node.hasAttribute ? // non-IE6/7
node.src :
// see http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx
node.getAttribute("src", 4)
} // For Developers
seajs.resolve = id2Uri
这段代码是用来进行路径处理的:
首先定义了一组正则表达式用来路径分析
dirname函数:获得一组路径的目录部分,比如dirname("a/b/c.js?t=123#xx/zz") 获得的结果是a/b
realpath函数:规范一组路径,比如realpath("http://test.com/a//./b/../c") ==> "http://test.com/a/c",就是将./ ../ 和//转换成规范的路径
normalize函数:规范一组路径的后缀名,比如normalize("path/to/a") ==> "path/to/a.js".
parseAlias函数:路径别名处理,根据别名id返回别名
parsePaths:解析配置中的path,具体可以参考config用法
parseVars:解析配置中的变量
parseMap:解析配置中的map
addBase:将路径转换为完整路径
id2Uri:将模块id转换为真实完整路径
util-deps.js:
/**
* util-deps.js - The parser for dependencies
* ref: tests/research/parse-dependencies/test.html
*/ var REQUIRE_RE = /"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|\/\*[\S\s]*?\*\/|\/(?:\\\/|[^\/\r\n])+\/(?=[^\/])|\/\/.*|\.\s*require|(?:^|[^$])\brequire\s*\(\s*(["'])(.+?)\1\s*\)/g
var SLASH_RE = /\\\\/g function parseDependencies(code) {
var ret = [] code.replace(SLASH_RE, "")
.replace(REQUIRE_RE, function(m, m1, m2) {
if (m2) {
ret.push(m2)
}
}) return ret
}
解析模块代码中require的模块,也就是依赖模块解析
【Seajs源码分析】2. 工具方法1的更多相关文章
- jQuery源码分析_工具方法(学习笔记)
expando:生成唯一JQ字符串(内部使用) noConflict():防止冲突 isReady:DOM是否加载完成(内部) readyWait:等待多少文件的计数器(内部) holdReady() ...
- JavaScript 模块化及 SeaJs 源码分析
网页的结构越来越复杂,简直可以看做一个简单APP,如果还像以前那样把所有的代码都放到一个文件里面会有一些问题: 全局变量互相影响 JavaScript文件变大,影响加载速度 结构混乱.很难维护 和后端 ...
- JUC源码分析-其它工具类(一)ThreadLocalRandom
JUC源码分析-其它工具类(一)ThreadLocalRandom ThreadLocalRandom 是 JDK7 在 JUC 包下新增的随机数生成器,它解决了 Random 在多线程下多个线程竞争 ...
- 鸿蒙内核源码分析(构建工具篇) | 顺瓜摸藤调试鸿蒙构建过程 | 百篇博客分析OpenHarmony源码 | v59.01
百篇博客系列篇.本篇为: v59.xx 鸿蒙内核源码分析(构建工具篇) | 顺瓜摸藤调试鸿蒙构建过程 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿 ...
- html2canvas实现浏览器截图的原理(包含源码分析的通用方法)
DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师. 官方网站:devui.design Ng组件库:ng-devui(欢 ...
- vuex 源码分析(一) 使用方法和代码结构
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,注意:使用前需要先加载vue文件才可以使用(在node.js下需要使用Vue.use(Vuex ...
- external-attacher源码分析(1)-main方法与启动参数分析
更多 ceph-csi 其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 摘要 ceph-csi分析-external-attacher源码分析.external- ...
- 【Seajs源码分析】1. 整体架构
seajs是一个非常流行的模块开发引擎,目前项目中使用比较多,为了深入了解已经改进seajs我阅读了他的源码,希望对自己的代码生涯能有所启发. 本文说介绍的是指seajs2.3.3版本. 首先seaj ...
- zepto源码学习-02 工具方法-详细解读
上一篇:地址 先解决上次留下的疑问,开始看到zepto.z[0]这个东西的时候,我很是不爽,看着它都不顺眼,怎么一个zepto的实例对象var test1=$('#items'); test__pr ...
- axios 源码分析(上) 使用方法
axios是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它可以在浏览器和node环境下运行,在github上已经有六七万个星了,axios使用很方便,很多人在使用他,vu ...
随机推荐
- Android模拟器Intel Atom下载安装配置
https://software.intel.com 在Android x86模拟器Intel Atom x86 System Image时提示Intel execute disable bit(xd ...
- java处理json的工具类(list,map和json的之间的转换)
需要下载第三方的jar :net.sf.json import java.io.BufferedReader; import java.io.InputStream; import java.io.I ...
- Job流程:Mapper类分析
此文紧接Job流程:决定map个数的因素,Map任务被提交到Yarn后,被ApplicationMaster启动,任务的形式是YarnChild进程,在其中会执行MapTask的run()方法.无论是 ...
- 10个足以让你成为更优秀的程序员的C语言资源
一些人觉得编程无聊,一些人觉得它很好玩.但每个程序员都必须紧跟编程语言的潮流.大多数程序员都是从C开始学习编程的,因为C是用来写操作系统.应用程序最常用的语言. · C编程笔记 这些是华盛顿实验学院C ...
- creator cocos2d-js-min.js 文件廋身 变小 太大解决方法
使用的 cocos creator 1.2 版本, 菜单栏 项目 -- 项目设置 -- 模块设置 里面 把不要的模块去掉
- 何为K-邻近算法
答:K-邻近算法,英文为K-nearest neighbor(KNN),就是计算要测试对象与k个样本对象之间的距离,通过距离的大小来对测试对象进行分类
- RabbitMQ延迟队列
rabbitmq延迟队列 rabbitmq实现延迟队列用了rabbitmq-delayed-message-exchange插件,需要提前安装,并启用. 原理 其原理是通过Exchange来实现延迟功 ...
- vue.js的一些小语法v-for,v-text,v-html,v-on:click
1.Vue的目录结构: ======================================================================================== ...
- js梳理
js引用类型 Object Function Array其他皆为基本类型,这和很多高级语言不一样,需要注意!!!! typeof对应基本类型来说更实用---- typeof undefined ...
- codeforces 1A - math - ceil
2017-08-24 15:42:30 writer: pprp 感觉自己好菜啊,这个题都没有做的很好 题意很简单,用a * a 的地砖,将 n * m 的地板铺满,问最少需要多少个地砖? 一开始打算 ...