首页 > 代码库 > 开坑!JavaScript AMD模块的设计与实现

开坑!JavaScript AMD模块的设计与实现

开个坑,慢慢学习总结JavaScript的AMD规范

先把自己写的一个简易实现放上来,然后慢慢从0開始解说一下AMD,以及怎样自己动手实现一个AMD

(function(w, DOC) {
	var _$ = w.$;
	var head = DOC.head || DOC.getElementsByTagName(‘head‘)[0];
	var html = DOC.documentElement;
	var W3C = DOC.dispatchEvent;
	var basePath = getCurrentScript(DOC);
	basePath = basePath.substring(0, basePath.lastIndexOf(‘/‘) + 1);
	var hasOwn = Object.prototype.hasOwnProperty;
	var toString = Object.prototype.toString;
	var class2type = {
		
	};

	var noop = function() {};

	var AS = function() {
		if (this == w) {
			return new AS(arguments);
		} else {
			console.info(this);
		}
	};
	AS.prototype = {
		constructor: AS
	};
	AS.fn = AS.prototype;
	AS.extend = function() {
		var args = arguments;
		if (args.length === 2) {
			var target = args[0];
			var source = args[1];
			for(var attr in source) {
				target[attr] = source[attr]; 
			};
		} else {
			for(var i = 0, len = args.length; i < len; i++) {
				var obj = args[i];
				for(var attr in obj) {
					AS[attr] = obj[attr]; 
				};
			};
		};
	};

	/*AMD模块開始*/
	var modules = {};

	function getEmptyModule() {
		return {
			deps: [],
			offers: [],
			state: 0,
			factory: noop
		};
	};

	function getCurrentScript(DOC) {
		if (DOC.currentScript) {
			return DOC.currentScript.src; //FF,Chrome
		};
		var stack;
		try {
			a.b.c();
		} catch (e) {
			stack = e.stack; // 利用错误异常立马抛出高速获得当前载入文件路径
			if (!stack && window.opera) {
				stack = String(e);
				if (!stack && window.opera) {
					stack = (String(e).match(/of linked script \S+/g) || []).join(" ");
				}
			};
		};
		if (stack) {
			stack = stack.split(/[@ ]/g).pop(); //取得最后一行,最后一个空格或@之后的部分
			stack = stack[0] === "(" ? stack.slice(1, -1) : stack;
			return stack.replace(/(:\d+)?:\d+$/i, ""); //去掉行号与也许存在的出错字符起始位置
		}
		// IE
		var nodes = head.getElementsByTagName("script");
		for (var i = 0, node; node = nodes[i++];) {
			if (node.readyState === ‘interactive‘) {
				return node.src;
			};
		};
	}

	function getModuleName(url) {
		return url.substring(url.lastIndexOf(‘/‘) + 1, url.lastIndexOf(‘.js‘));
	}

	function require(list, factory) {
		var loaded = 0;
		var requires = list.length;
		var args = [];
		var id = getCurrentScript(DOC);
		console.info(‘载入‘+getModuleName(id)+‘模块须要依赖‘+ list+‘模块‘)
		var module = modules[id] ? modules[id] : getEmptyModule();
		module[‘factory‘] = factory;
		modules[id] = module;

		for (var i = 0; i < list.length; i++) {
			var depId = basePath + list[i] + ‘.js‘;
			modules[depId] = modules[depId] ? modules[depId] : getEmptyModule();
			module[‘deps‘].push(depId);
			if (modules[depId] && modules[depId].state === 2) {
				console.info(getModuleName(depId)+‘依赖已提前载入完成‘); 
				modules[depId].offers.push(id);
				loaded++;
				args.push(modules[depId].exports);
				//此依赖模块正在被载入中
			} else if (modules[depId] && modules[depId].state === 1) {
				console.info(getModuleName(depId)+‘依赖正在载入中‘); 
				modules[depId].offers.push(id);
				//此依赖模块从未载入过
			} else {
				//loadJS载入模块js,模块js调用define,define又会require载入此模块须要的依赖
				//从而函数进入递归追踪并载入此模块全部直接和间接依赖
				console.info(‘第一次载入依赖模块‘ + getModuleName(depId)); 
				modules[depId].offers.push(id);
				loadJS(depId);
			};
		};
		if (loaded === requires) {
			module.factory.apply(null, args);
			module.state = 2;
		};
	};
	window.require = AS.require = require;

	function loadJS(url) {
		var module = modules[url];
		var node = DOC.createElement(‘script‘);
		node.onload = node.onreadystatechange = function() {
			if (/loaded|complete/i.test(node.readyState) || !node.readyState) {

			};
		};
		node.src = http://www.mamicode.com/url;>

开坑!JavaScript AMD模块的设计与实现