【SeaJS】【3】seajs.data相关的源码阅读

简介:

   在SeaJS官网上推荐了源码阅读顺序,本文并没有采用这个顺序,而是按个人习惯以调试官方示例的方式进行源码阅读。早期版本作者玉伯使用了几个闭包形式,本文源码版本为2.1.1,它的编码方式个人认为更加脚本化,该版本代码量不到1K。


1. 使用Chrome打开《【SeaJS】【1】初识SeaJS》中的hello.html文件,按F12打开JavaScript控制台,依次选择Source > sea.js,可以看到SeaJS使用了一个大的闭包:

(function(global, undefined)

{  

   if(global.seajs){

      return;

   }

   //...略

})(this);



说明:this是Window对象,同时把Window对象赋值给global变量,这样在这个闭包中使用Window的地方均可以用global代替。



2. hello.html文件中使用<script s rc="../sea-modules/seajs/seajs/2.1.1/sea.js"></script>引入sea.js,所以浏览器解析html文件时会加载sea.js代码。加载完sea.js后Window对象结构如图一:

(图一)


3. 从上图中可以看到seajs的初始值的大体轮廓,下面我们看一下seajs.data值的由来:

// 定义seajs.data变量对象

var data = seajs.data = {};


// 定义seajs.data的事件集合

var events = data.events = {};


// 定义已加载模块的集合

var fetchedList = {};

data.fetchedList = fetchedList;

// 设置字符集

data.charset = "utf-8";


// 定义获取依赖模块个数方法

var _cid = 0;

function cid(){

   return _cid++;

}

data.cid =cid;


// 把document和location对象赋值给doc、loc

var doc = document;

var loc = location;


// 通过文档location对象获取hello.html文件所在的路径,并把其赋给data.cwd作为当前工作路径

var DIRNAME_RE = /[^?#]*\//

function dirname(path){

   return path.match(DIRNAME_RE)[0];

}


var cwd = dirname(loc.href);

data.cwd = cwd;


// 通过文档document对象读取hello.html文件中引入seajs的路径,并把其设置为加载路径

function getScriptAbsoluteSrc(node){

   return node.hasAttribute ? node.src : node.getAttribute("src", 4);

}


var scripts = doc.getElementsByTagName("script");

var loaderScript = doc.getElementById("seajsnode") || scripts[scripts.length - 1];

var loaderDir = dirname(getScriptAbsoluteloaderScript ) || cwd);

data.dir = loaderDir;



说明:dirname()函数的逻辑

(1)URL路径的基本知识

   常见URL写法如http://www.baidu.com。

   当在百度中搜索“url”字符串时,浏览器显示的url为http://www.baidu.com/s?wd=url,用?表示后面跟随的是参数;

   当在谷歌中搜索“url”字符串时,浏览器显示的url值为http://www.google.com.hk/#fp=11d84258cf3e1c4a&q=url,其中#是指导浏览器动作的,对服务端没有任何用途。关于URL中#号的作用,感兴趣的读者可以参考《http://www.ruanyifeng.com/blog/2011/03/url_hash.html》。

(2)入参path的值为file:///E:/seajs/officialsample/app/hello.html,而DIRNAME_RE正则表达式的含义原来“不是?或#的0个或多个字符 + / ”,由于*在正则表达式中是贪婪的,所以它匹配的值为[file:///E:/seajs/officialsample/app/],然后取集合中的第一个,所以函数返回的值为file:///E:/seajs/officialsample/app/





说明:getScriptAbsoluteSrc()函数的逻辑

function getScriptAbsoluteSrc(node){

   return node.hasAttribute ? node.src : node.getAttribute("src", 4);

}

(1)入参node的值为loaderScript,经上面初始化后loaderScript值为<script s rc="../sea-modules/seajs/seajs/2.1.1/sea.js" />

(2)在非IE6、IE7中node具有hasTrribute属性,所以此处为了兼容IE6、IE7这里使用了node.getAttribute("src", 4)方法,获取node对象中的src对应值



// 从加载路径中获取seajs所属路径作为根路径

var BASE_RE = /^(.+?\/)(\?\?)?(seajs\/)+/

data.base = (loaderDir.match(BASE_RE) || ["", loaderDir])[1];


说明:解释BASE_RE正则表达式

(1)它分为三部分^(.+?\/)、(\?\?)?和(seajs\/)+,第一部分匹配以xxx/格式开头的字符串,第二部分匹配零个或多个??,第三部分匹配一个或多个seajs/字符串

(2)match()表示:如果没有找到任何匹配的文本将返回null,否则它将返回一个数组。该数组的第0个元素存放的是匹配文本,而其余的元素存放的是与正则表达式的子表式匹配的文本

(3)由于loaderDir的值为file:///E:/seajs/officialSmaple/sea-modules/seajs/seajs/2.1.1/,匹配之后的值为["file:///E:/seajs/", "file:///E:/", undefined, "seajs/" ],所以data.base的值为file:///E:/










     本文转自qingkechina 51CTO博客,原文链接:http://blog.51cto.com/qingkechina/1272820,如需转载请自行联系原作者



相关文章
|
JavaScript 前端开发 UED
单文件组件(Single-File Components):Vue.js开发的模块化之道
Vue.js是一款流行的JavaScript框架,以其简洁、灵活和易用而广受欢迎。其中一个Vue.js的强大功能就是单文件组件(Single-File Components),它使得Vue.js应用的开发更加模块化和可维护。在本博客中,我们将深入探讨单文件组件的概念、结构、用法,以及如何利用它们来构建清晰、可复用和高效的Vue.js应用。
262 0
|
JavaScript 前端开发
FastAdmin中RequireJs是如何调用的
FastAdmin中RequireJs是如何调用的
550 0
|
设计模式 JavaScript
《XDM,JS如何函数式编程?看这就够了!(五)》
本篇是《JS如何函数式编程》系列第五篇!共七篇,似乎已经能望见胜利的彼岸了!!!
|
JavaScript 程序员 开发者
XDM,JS如何函数式编程?看这就够了!(三)
没错,本篇就是谈关于 “组合函数”。它是函数编程的重中之重之重之重重重!
|
JavaScript 前端开发 开发者
XDM,JS如何函数式编程?看这就够了!(七)
如果我们的代码夹杂着命令式风格和声明式风格,即处在 图1.2 红线和绿线的交叉点上的话,那我们代码的可读性或许就处在 图 1.1 虚线和实线的交叉点上,可读性非常低。所以,我们在 JS 函数式编程的路上要更加一往无前!别到最后不伦不类,沦为笑柄 Orz
|
JavaScript 前端开发
XDM,JS如何函数式编程?看这就够了!(二)
本篇将着重介绍第 2 点中函数的输入,它是 JS 轻量函数式编程的基础之基础,重要之重要!!!
|
JavaScript 前端开发
XDM,JS如何函数式编程?看这就够了!(六)
我们前篇谈了很多关于【闭包】的理解了,所以你应该会知道,我们现在将要谈的就是 ——【异步】
|
JavaScript 前端开发 C#
requireJS的基本用法(下)
requireJS的基本用法(下)
170 0
requireJS的基本用法(下)
|
JavaScript 前端开发 Go
requireJS的基本用法(上)
requireJS的基本用法
193 0
requireJS的基本用法(上)
|
JavaScript 前端开发 应用服务中间件