【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对象结构如图一:

223141103.jpg

(图一)


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,如需转载请自行联系原作者



相关文章
|
6月前
|
JavaScript
深入剖析Vue.js源码:探寻ref的神奇之处,为什么它比reactive更强大?
深入剖析Vue.js源码:探寻ref的神奇之处,为什么它比reactive更强大?
深入剖析Vue.js源码:探寻ref的神奇之处,为什么它比reactive更强大?
|
前端开发
前端学习案例16-js中的HMR
前端学习案例16-js中的HMR
47 0
前端学习案例16-js中的HMR
|
JavaScript 前端开发 Go
requireJS的基本用法(上)
requireJS的基本用法
129 0
requireJS的基本用法(上)
|
JavaScript 前端开发 C#
requireJS的基本用法(下)
requireJS的基本用法(下)
126 0
requireJS的基本用法(下)
一篇文章掌握Egg.js的核心用法
一篇文章掌握Egg.js的核心用法
119 0
一篇文章掌握Egg.js的核心用法
|
中间件
Egg.js中间件的核心用法
Egg.js中间件的核心用法
307 0
|
中间件
Egg.js中路由的核心用法
Egg.js中路由的核心用法
154 0
|
安全 中间件
学习 | egg.js 中间件和插件
小小又开始学习了,这次学习的是中间件和插件。 这次将会对这两个点,进行学习。
930 1