【Seajs源碼分析】2. 工具方法1

Sea.js:css

var seajs = global.seajs = { // The current version of Sea.js being used
  version: "@VERSION" } var data = seajs.data = {}

代碼定義了一個seajs變量並暴露給全局,變量如今只有一個值就是版本號變量html

另外定義了一個data變量,後面會用到 node

util-lang.jsgit

/** * 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博客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用來觸發事件以及事件綁定的函數app

 util-path.jsjsp

/** * 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的模塊,也就是依賴模塊解析

相關文章
相關標籤/搜索