`
Mossad
  • 浏览: 82803 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

小米10月15日抢购前端代码分析

 
阅读更多

首先感谢huangzhir同学的小米抢购前端代码分析,我分析的代码也是从他那里拿的,这篇文章只想为自己留个备份,大家有兴趣也可以看一看,可能有些东西对你有所帮助也说不定。直接贴代码:

var isRollStatus = false, isPhone = false, isBox = false;
(function() {
	m = {
		arrelems : [],//没用到
		ready : null,
		doms : function() {
			var _this = this;
			var isReady = false;
			var readyList = [];
			var timer;
			_this.ready = function(fn) {
				if (isReady) {
					fn.call(document);//直接执行,这样就readyList没用了,所以readyList虽然是数组,但其实只会有一个函数元素。
				} else {
					readyList.push(function() {
						return fn.call(this);//执行的时候this指向document。
					});
				};
				return this;
			};
			var onDOMReady = function() {
				for ( var i = 0x0; i < readyList.length; i++) {
					readyList[i].apply(document);
				};
				readyList = null;
			};
			var bindReady = function(evt) {
				if (isReady) {//因为IE6,IE7用到了setInterval,所以这里需要判断isReady的状态。
					return;
				}
				isReady = true;
				onDOMReady.call(window);//直接调用onDOMReady()效果一样。
				if (document.removeEventListener) {
					document.removeEventListener(_$[0], bindReady, false);//'DOMContentLoaded'
				} else if (document.attachEvent) {
					document.detachEvent(_$[1], bindReady);//'onreadystatechange'
					if (window == window.top) {
						clearInterval(timer);
						timer = null;
					}
				}
			};
			/**
			 * 监听document是否completely loaded and parsed,yes就call绑定函数bindReady。
			 * stylesheets loading会block绑定函数的执行,但图片不会。
			 * 这里用了三种方法hack不同的浏览器:
			 * 	1、IE9和Chrome,Firefox等主流浏览器:直接绑定DOMContentLoaded时间到document。
			 * 	2、IE8:监听onreadystatechange事件并测试状态。
			 * 	3、IE6,IE7:document.documentElement.doScroll('left')在ready之前会一直抛错。
			 */
			if (document.addEventListener) {//IE9支持document.addEventListener方法
				document.addEventListener(_$[2], bindReady, false);//'DOMContentLoaded'
			} else if (document.attachEvent) {//IE8
				//https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded
				document.attachEvent(_$[3], function() {//'onreadystatechange'
					if ((/loaded|complete/).test(document.readyState))
						bindReady();
				});
				if (window == window.top) {//window == window.top是用来做什么的?
					timer = setInterval(function() {//IE6,IE7
						try {
							isReady || document.documentElement.doScroll(_$[4]);//'left'
						} catch (e) {
							return
						}
						bindReady();
					}, 0x5);
				}
			}
		},
		$ : function() {
			return typeof arguments[0x0] === _$[5] ? document//'string'
					.getElementById(arguments[0x0]) : arguments[0x0];
		},
		extend : function(target, options) {//没用到
			for (name in options) {
				target[name] = options[name];
			}
			return target;
		},
		cookie : function(key, value, options) {
			/**
			 * 下面这段代码负责cookie的添加和删除, 在jquery.cookie.js中删除cookie有专门的方法removeCookie,
			 * 小米在这里把添加和删除合并是为了简便起见。
			 * 不过话说String(value) !== _$[6]有什么用?
			 */
			if (arguments.length > 0x1 && String(value) !== _$[6]) {//6: '[object Object]'
				if (value === null || value === undefined) {
					options.expires = -0x1;
				};
				if (typeof options.expires === _$[7]) {//'number'
					var days = options.expires, t = options.expires = new Date();
					t.setDate(t.getDate() + days);
				};
				value = String(value);
				return (document.cookie = [
						encodeURIComponent(key),
						_$[8],//'='
						options.raw ? value : encodeURIComponent(value),
						options.expires ? _$[9] + options.expires.toUTCString() : _$[10],//'; expires=',用的方法是UTC不是GMT。
						options.path ? _$[11] + options.path : _$[12],//11: '; path='
						options.domain ? _$[13] + options.domain : _$[14],//13: '; domain='
						options.secure ? _$[15] : _$[16] ].join(_$[17]));//15: '; secure'
			};
			/**
			 * 这个判断同样没有意义,代码走到这里说明调用参数只有一个m.cookie(key)或者没有m.cookie(),
			 * 所以value一定是undefined,直接写成options = {}就好了。
			 */
			options = value || {};
			//唉,options.raw!
			var result, decode = options.raw ? function(s) {
				return s;
			} : decodeURIComponent;
			return (result = new RegExp(_$[18] + encodeURIComponent(key)//'(?:^|; )' + key + '=([^;]*)'
					+ _$[19]).exec(document.cookie)) ? decode(result[0x1])
					: null;
		},
		addEvent : (function() {//没用到
			if (document.addEventListener) {
				return function(el, type, fn) {
					el.addEventListener(type, fn, false);
				};
			} else {
				return function(el, type, fn) {
					el.attachEvent(_$[20] + type, function() {//'on'
						return fn.call(el, window.event);//window.event
					});
				};
			}
		})(),
		randomDiff : function(option) {//没用到
			var paras = {
				randomS : 0x1,
				randomE : 0x5
			}, options = m.extend(paras, option || {}), randomNum = Math
					.random()
					* (options.randomE - options.randomS + 0x1)
					+ options.randomS;
			return parseInt(randomNum);
		},
		getQueryString : function(name) {//没用到
			var reg = new RegExp(_$[21] + name + _$[22], _$[23]);//'(^|&)', '=([^&]*)(&|$)', 'i'
			var r = window.location.search.substr(0x1).match(reg);
			if (r != null)
				return unescape(r[0x2]);
			return null;
		},
		creatJs : function(src, elemid) {
			var Scrip = document.createElement(_$[24]);//'script'
			Scrip.src = src;
			if (!!elemid) {
				Scrip.id = elemid;
				if (m.$(elemid)) {
					document.body.removeChild(m.$(elemid));
				}
			}
			document.body.appendChild(Scrip);
		},
		/**
		 * 如果有name='orgin'且value='mapp'的cookie就认为是用户从PC机登录,且删除该cookie并返回,否则就认为是Mobile登录,
		 * 确认后跳转至Mobile登录页面。由此可猜测该cookie在用PC机登录小米首页的时候被创建了,但是Mobile登录时就没有创建或者值不同。
		 * @param url
		 */
		phone : function(url) {
			url = url || _$[25];//25: 'http://m.xiaomi.com'
			if (m.cookie(_$[26]) === _$[27]) {//26: 'orgin', 27: 'mapp'
				m.cookie(_$[28], null, {//'orgin'
					path : _$[29],//'/'
					domain : _$[30]//'.xiaomi.com'
				});
				return
			};
			var sUserAgent = navigator.userAgent;
			if (sUserAgent.indexOf(_$[31]) > -0x1//'Android'
					|| sUserAgent.indexOf(_$[32]) > -0x1//'iPhone'
					|| sUserAgent.indexOf(_$[33]) > -0x1//'iPod'
					|| sUserAgent.indexOf(_$[34]) > -0x1) {//'Symbian'
				location.href = url;
			}
		},
		init : function() {
			var _this = this;
			_this.doms();
		}
	};
	m.init();
})();

var json_1022 = {//这个数据是10月22号抢购的时候截取下来的,传递给hdcontrol的参数。
		"stime": 1382414432,//server端的时间
		"status": {
			"allow": false,
		    "miphone": {
		    	"hdstart": true,
		    	"hdstop": false,
		    	"hdurl": "?_a=20131022_phone_df56ab516d&_op=choose",
		    	"duration": null,
		    	"pmstart": false
		    },
		    "mibox": {
		    	"hdstart": true,
		    	"hdstop": false,
		    	"hdurl": "?_a=20131022_box_f9348273e1&_op=choose",
		    	"duration": null,
		    	"pmstart": false
		    },
		    "mitv": {
		    	"hdstart": true,
		    	"hdstop": false,
		    	"hdurl": "?_a=20131022_mi_tv_ae3cc600f&_op=choose",
		    	"duration": null,
		    	"pmstart": false
		    }
		}
	};
function hdcontrol(json) {//更新client和server的时间差;根据server给的状态位,显示当前手机和电视的购买情况(在售或已售完)。
	var phonestart = json.status.miphone.hdstart, phonestop = json.status.miphone.hdstop, boxstart = json.status.mibox.hdstart, boxstop = json.status.mibox.hdstop;
	servertime = downServertime = json.stime;
	var diffTime = parseInt(servertime - miphoneBuy.localTime());
	m.cookie(_$[35], diffTime, {//'xm_difft_hd'
		path : _$[36],//'/'
		domain : _$[37],//'.xiaomi.com'
		expires : 0x1//一天有效期
	});
	if (isRollStatus) {//点击购买窗口的购买按钮才会将isRollStatus置为true
		if (json.status.allow) {//购买成功?
			if (isPhone === true) {//你买的是手机吗?
				isPhone === false;//===应该是=
				if (json.status.miphone.hdurl == null || json.status.miphone.hdurl == _$[38]) {//''
					window.location.reload();
				} else {
					location.href = _$[39] + json.status.miphone.hdurl;//'http://t.hd.xiaomi.com/s/' + '?_a=20131022_phone_df56ab516d&_op=choose'
				}
			} else if (isBox === true) {//还是买的电视?
				isBox === false;//===应该是=
				if (json.status.mibox.hdurl == _$[40] || json.status.mibox.hdurl == null) {//''
					window.location.reload();
				} else {
					location.href = _$[41] + json.status.mibox.hdurl;//'http://t.hd.xiaomi.com/s/' + '?_a=20131022_box_f9348273e1&_op=choose'
				}
			}
		}
		isRollStatus = false;
	}
	if (phonestart === true && phonestop === false && boxstart === false
			&& boxstop === true) {
		m.cookie(_$[42], 0x1, {//'xm_xt_obox'
			path : _$[43],//'/'
			domain : _$[44],//'.xiaomi.com'
			expires : 0x1
		});
		m.cookie(_$[45], null, {//'xm_xt_ophone'
			path : _$[46],//'/'
			domain : _$[47]//'.xiaomi.com'
		});
		miphoneBuy.box(false);
		stepHtml.five();
	}
	if (phonestart === false && phonestop === true && boxstart === true
			&& boxstop === false) {
		m.cookie(_$[48], 0x1, {//'xm_xt_ophone'
			path : _$[49],
			domain : _$[50],
			expires : 0x1
		});
		m.cookie(_$[51], null, {//'xm_xt_obox'
			path : _$[52],
			domain : _$[53]
		});
		miphoneBuy.box(false);
		stepHtml.six();
	}
	if (phonestart === false && phonestop === true && boxstart === false
			&& boxstop === true) {
		m.cookie(_$[54], 0x1, {//'xm_xt_pre'
			path : _$[55],
			domain : _$[56],
			expires : 0x1
		});
		m.cookie(_$[57], null, {//'xm_xt_obox'
			path : _$[58],
			domain : _$[59]
		});
		m.cookie(_$[60], null, {//'xm_xt_ophone'
			path : _$[61],
			domain : _$[62]
		});
		miphoneBuy.saleOut();
	}
};
var miphoneBuy = {
	localTime : function() {//取client端时间,单位是秒
		return parseInt(new Date().getTime() / 0x3e8);
	},
	jsonInter : function() {//从server取数据并回调hdcontrol函数
		var timestamp = new Date().getTime();//这里的时间取的是本地时间戳
		m.creatJs(_$[63] + timestamp, _$[64]);//63: 'http://tc.hd.xiaomi.com/hdget?callback=hdcontrol&_=', 64: 'jsonp'
	},
	checkCookie : function() {
		var _this = this;
		if (m.cookie(_$[65])) {//'xm_xt_pre'
			_this.saleOut();//对哟,你来的太晚,已全部售完,我的心你不明白--《你把我灌醉》
		} else {
			if (!m.cookie(_$[66])) {//'xm_difft_hd'
				_this.jsonInter();//这里主要用来取client和server的时间差
			}
			setTimeout(function() {
				servertime = downServertime = miphoneBuy.localTime() + parseInt(m.cookie(_$[67]));//'xm_difft_hd',重算一下servertime和downServertime
				_this.jugeStatus();
			}, 0x64);//留一点时间给jsonInter加载js文件和执行
		}
	},
	saleOut : function() {//全部已售完
		if (window.timeInter) {//全没了,通知广大用户这一噩耗,定时器?也不用了!
			clearInterval(timeInter);
		}
		stepHtml.four();
		miphoneBuy.box(false);
	},
	jugeStatus : function() {//更新时间节点和页面状态
		var _this = this;
		_this.timeNode();
		timeInter = window.setInterval(function() {
			_this.timeNode();
			servertime++;
		}, 0x3e8);//1000ms
	},
	configs : {
		startDate : new Date(_$[68]).getTime(),//'10/15/2013  12:00:00'
		preLogMin : 0x1e//30 mins
	},
	timeNode : function() {
		var _this = this;
		var nowTime = servertime * 0x3e8, startTime = _this.configs.startDate, preLogTime = startTime - _this.configs.preLogMin * 0xea60;
		if (m.cookie(_$[69])) {//'xm_xt_pre'
			_this.saleOut();
			return
		}
		if (m.cookie(_$[70])) {//'xm_difft_hd'
			downServertime = miphoneBuy.localTime() + parseInt(m.cookie(_$[71]));//'xm_difft_hd'
		}
		//更新页面信息用的是servertime,而且是以ms为单位;更新倒计时窗口用的是downServertime;
		if (nowTime < preLogTime) {//未进入30分钟倒计时
			stepHtml.one();
			_this.timeOut();
		} else if (nowTime >= preLogTime && nowTime < startTime) {//进入倒计时但尚未开始,提醒用户先登录
			stepHtml.two();
			_this.timeOut();
		} else if (nowTime >= startTime) {//已经开售,正式拉开抢购大幕
			if (m.cookie(_$[72])) {//'xm_xt_obox'
				stepHtml.five();
			} else if (m.cookie(_$[73])) {//'xm_xt_ophone'
				stepHtml.six();
			} else {
				stepHtml.three();
			}
		}
	},
	timeOut : function() {
		var _this = this;
		_this.SetRemainTime();
		if (window.InterValObj) {
			clearInterval(InterValObj);
		}
		/**
		 * 这一个InterValObj定时器用的多余,因为在抢购开始之前timeNode方法本身就会被每秒执行一次,
		 * 于是timeOut也会被每秒执行一次,这里InterValObj相关的代码可以全部去掉,效果一样!
		 */
		InterValObj = window.setInterval(function() {
			_this.SetRemainTime();
		}, 0x3e8);
	},
	SetRemainTime : function() {//更新页面倒计时按钮的时间信息,提醒用户抢购什么时候开始。
		var _this = this, endtime = _this.configs.startDate, setEndtime = endtime / 0x3e8;
		surplusTime = setEndtime - downServertime;
		if (surplusTime >= 0x0) {
			var second = Math.floor(surplusTime % 0x3c), minite = Math
					.floor((surplusTime / 0x3c) % 0x3c), hour = Math
					.floor((surplusTime / 0xe10) % 0x18), day = Math
					.floor((surplusTime / 0x15180) % 0x1e);
			downServertime++;
			var timeArray = [ second.toString(), minite.toString(),
					hour.toString(), day.toString() ];
			var timeText = _$[74] + timeArray[0x2] + _$[75] + timeArray[0x1]//几小时几分几秒后开始
					+ _$[76] + timeArray[0x0] + _$[77];
			if (hour === 0x0) {
				timeText = _$[78] + timeArray[0x1] + _$[79] + timeArray[0x0]//几分几秒后开始
						+ _$[80];
				if (minite === 0x0) {
					timeText = _$[81] + timeArray[0x0] + _$[82];//几秒后开始
				}
			}
			
			if (!!m.$(_$[83])) {//'surTime',倒计时窗口ID
				m.$(_$[84]).innerHTML = timeText;//'surTime'
			}
		} else {
			if (window.InterValObj) {
				clearInterval(InterValObj);
			}
		}
	},
	box : function(bool) {//true: 打开购买窗口,false:关闭购买窗口
		if (bool) {
			var mboxbg = m.$(_$[85]);//'boxbg'
			var mbox = m.$(_$[86]);//'box'
			mboxbg.style.height = Math.max(
					document.documentElement.clientHeight,
					document.documentElement.scrollHeight)
					+ _$[87];//'px'
			mboxbg.style.display = _$[88];//'block'
			mbox.style.display = _$[89];//'block'
		} else {//关闭购买窗口;disable购买按钮并update显示文本为倒计时状态;重置倒计时的读秒
			var mboxbg = m.$(_$[90]);//'boxbg',遮罩层
			var mbox = m.$(_$[91]);//'box',弹出的购买窗口
			mboxbg.style.display = _$[92];//'none'
			mbox.style.display = _$[93];//'none'
			if (window.rollInter) {
				clearInterval(rollInter);
			}
			Util.retime();//下面的count变量已经被重置
			m.$(_$[94]).innerHTML = _$[95] + count + _$[96];//94: 'reback', 95: '重新进入(<span id=\'initCount\'>', 96: '</span>)'
		}
	},
	init : function(option) {
		var _this = this;
		_this.checkCookie();
	}
};
var stepHtml = {//,
	/**
	 * 购买手机:showBox('phone');购买电视:showBox('box')
	 * 凡是带有"购买"字样的都是调用showBox,其他的"查询"和"支付"都是超链接
	 */
	one : function() {//即将开始
		var mhtml = stepHtml.htmlString();
		m.$(_$[97]).innerHTML = mhtml.btn[0x0];//_$[141]: '<span class="untime"><label id="surTime" class="unbtn"></label></span>'
		m.$(_$[98]).innerHTML = mhtml.subTitle[0x0];//_$[147]: ''
		m.$(_$[99]).innerHTML = mhtml.lnks[0x0];//_$[156]: '手机预约查询&电视预约查询'
		m.$(_$[100]).innerHTML = mhtml.phonebtn[0x0];//_$[161]: '<span>1999元(16GB)</span>即将开始'
		m.$(_$[101]).innerHTML = mhtml.tvbtn[0x0];//_$[164]: '<span>2999元</span>即将开始'
		m.$(_$[102]).innerHTML = mhtml.msg[0x0];//_$[151]: ''
		m.$(_$[103]).innerHTML = mhtml.bottombtn[0x0];//_$[167]: '<label class="btn unbtn">即将开始</label>'
	},
	two : function() {//即将开始,提醒用户先登录
		var mhtml = stepHtml.htmlString();
		var miID = (m.cookie(_$[104]));//'userId'
		if (miID) {
			m.$(_$[105]).innerHTML = mhtml.btn[0x0];//_$[141]: '<span class="untime"><label id="surTime" class="unbtn"></label></span>'
		} else {
			m.$(_$[106]).innerHTML = mhtml.btn[0x1];//_$[141]: '<a>提前登录</a>'
		}
		m.$(_$[107]).innerHTML = mhtml.lnks[0x0];//_$[156]: '手机预约查询&电视预约查询'
		m.$(_$[108]).innerHTML = mhtml.subTitle[0x0];//_$[147]: ''
		m.$(_$[109]).innerHTML = mhtml.phonebtn[0x0];//_$[161]: '<span>1999元(16GB)</span>即将开始'
		m.$(_$[110]).innerHTML = mhtml.tvbtn[0x0];//_$[164]: '<span>2999元</span>即将开始'
		m.$(_$[111]).innerHTML = mhtml.msg[0x0];//_$[151]: ''
		m.$(_$[112]).innerHTML = mhtml.bottombtn[0x0];//_$[167]: '<label class="btn unbtn">即将开始</label>'
	},
	three : function() {//小米手机3和小米电视均可购买
		var mhtml = stepHtml.htmlString();
		m.$(_$[113]).innerHTML = mhtml.btn[0x2];//_$[143]: '购买手机&购买电视'
		m.$(_$[114]).innerHTML = mhtml.subTitle[0x0];//_$[147]: ''
		m.$(_$[115]).innerHTML = mhtml.phonebtn[0x1];//_$[162]: '<span>1999元(16GB)</span>立即购买'
		m.$(_$[116]).innerHTML = mhtml.tvbtn[0x1];//_$[165]: '<span>2999元</span>立即购买'
		m.$(_$[117]).innerHTML = mhtml.msg[0x4];//_$[155]: '购机成功用户请在3小时内下单,3小时内支付。支付手机&支付电视'
		m.$(_$[118]).innerHTML = mhtml.lnks[0x0];//_$[156]: '手机预约查询&电视预约查询'
		m.$(_$[119]).innerHTML = mhtml.bottombtn[0x1];//_$[168]: '购买手机'
	},
	four : function() {//全部小米手机3及小米电视已售罄
		var mhtml = stepHtml.htmlString();
		m.$(_$[120]).innerHTML = mhtml.btn[0x3];//_$[144]: '支付手机&支付电视'
		m.$(_$[121]).innerHTML = mhtml.phonebtn[0x2];//_$[163]: '<span>1999元(16GB)</span>立即支付'
		m.$(_$[122]).innerHTML = mhtml.tvbtn[0x2];//_$[166]: '<span>2999元</span>立即支付'
		m.$(_$[123]).innerHTML = mhtml.subTitle[0x3];//_$[150]: '全部小米手机3及小米电视已售罄'
		m.$(_$[124]).innerHTML = mhtml.msg[0x3];//_$[154]: '购机成功用户请在3小时内下单,3小时内支付。'
		m.$(_$[125]).innerHTML = mhtml.lnks[0x3];//_$[159]: '手机购买查询&电视购买查询'
		m.$(_$[126]).innerHTML = mhtml.bottombtn[0x2];//_$[169]: '支付手机'
	},
	five : function() {//小米电视已售罄,您可继续购买小米手机3
		var mhtml = stepHtml.htmlString();
		m.$(_$[127]).innerHTML = mhtml.btn[0x4];//_$[145]: '购买手机&支付电视'
		m.$(_$[128]).innerHTML = mhtml.phonebtn[0x1];//_$[162]: '<span>1999元(16GB)</span>立即购买'
		m.$(_$[129]).innerHTML = mhtml.subTitle[0x2];//_$[149]: '小米电视已售罄,您可继续购买小米手机3'
		m.$(_$[130]).innerHTML = mhtml.tvbtn[0x2];//_$[166]: '<span>2999元</span>立即支付'
		m.$(_$[131]).innerHTML = mhtml.msg[0x1];//_$[152]: '购机成功用户请在3小时内下单,3小时内支付。<a>支付手机</a>'
		m.$(_$[132]).innerHTML = mhtml.lnks[0x1];//_$[157]: '手机预约查询&电视购买查询'
		m.$(_$[133]).innerHTML = mhtml.bottombtn[0x1];//_$[168]: '购买手机'
	},
	six : function() {//小米手机3已售罄,您可继续购买小米电视
		var mhtml = stepHtml.htmlString();
		m.$(_$[134]).innerHTML = mhtml.btn[0x5];//_$[146]: '购买电视&购买电视'
		m.$(_$[135]).innerHTML = mhtml.phonebtn[0x2];//_$[163]: '<span>1999元(16GB)</span>立即支付'
		m.$(_$[136]).innerHTML = mhtml.subTitle[0x1];//_$[148]: '小米手机3已售罄,您可继续购买小米电视'
		m.$(_$[137]).innerHTML = mhtml.tvbtn[0x1];//_$[165]: '<span>2999元</span>立即购买'
		m.$(_$[138]).innerHTML = mhtml.msg[0x2];//_$[153]: '购机成功用户请在3小时内下单,3小时内支付。<a>支付电视</a>'
		m.$(_$[139]).innerHTML = mhtml.lnks[0x2];//_$[158]: '手机购买查询&电视预约查询'
		m.$(_$[140]).innerHTML = mhtml.bottombtn[0x2];//_$[168]: '支付手机'
	},
	htmlString : function() {
		var htmlSum = {
			btn : [ _$[141], _$[142], _$[143], _$[144], _$[145], _$[146] ],//hdBtns
			subTitle : [ _$[147], _$[148], _$[149], _$[150], ],//hdSubTitle
			msg : [ _$[151], _$[152], _$[153], _$[154], _$[155] ],//hdMsg
			lnks : [ _$[156], _$[157], _$[158], _$[159], _$[160], ],//hdLnks
			phonebtn : [ _$[161], _$[162], _$[163] ],//miphone
			tvbtn : [ _$[164], _$[165], _$[166] ],//mitv
			bottombtn : [ _$[167], _$[168], _$[169] ]//bottombtn
		};
		return htmlSum;
	}
};
var randomCount = parseInt(Math.random() * (0xa - 0x5 + 0x1) + 0x5), count = randomCount, CONFIG = {
	count : randomCount
}, Util = {
	time : function() {
		var b = m.$(_$[170]);//'reback',<a id="reback" class="reback_btn_next">进入活动</a>
		if (count === 0x0) {
			b.innerHTML = _$[171];//'进入活动'
			b.className = _$[172];//'reback_btn_next'
			this.start();
			return false;
		}
		count = count - 0x1;
		//只需要更新initCount元素的文本就好了,没必要更新reback的html
		b.innerHTML = _$[173] + count + _$[174];//173: '重新进入(<span id=\'initCount\'>', 174: '</span>)'
	},
	start : function() {
		var me = this, reback = m.$(_$[175]);//'reback'
		reback.onclick = function() {
			/**
			 * 向server发送请求,根据返回状态判断是否抢购成功;
			 * Disable购买按钮;
			 * 注意此时rollInter并没有被清除,也就是说从购买按钮已经可以点击到你真正点击的这段时间内Util.time一直
			 * 在执行,这里最好把rollInter清除掉。
			 */
			isRollStatus = true;//开始尝试购买,抢购进入高潮!
			miphoneBuy.jsonInter();
			me.retime();
			reback.onclick = null;
			return false;
		};
	},
	retime : function() {//重置购买按钮为disable状态;重置倒计时读秒。
		m.$(_$[176]).className = _$[177];//176: 'reback', 177: 'reback_btn'
		count = CONFIG.count;
	}
};
var loginInfo = {
	data : {
		userId : 0x0,
		userName : _$[178]//''
	},
	init : function() {
		this.data.userId = m.cookie(_$[179]);//'userId'
		if (!this.data.userId)
			return false;
		//这里this.data.userId已经是true了,所以this.data.userName一定被赋值为m.cookie('XM_' + this.data.userId + '_UN')
		this.data.userName = (this.data.userId) ? m.cookie(_$[180]//'XM_'
				+ this.data.userId + _$[181]) : _$[182];//181: '_UN', 182: ''
		if (this.data.userName == null || this.data.userName == _$[183]) {//''
			var script = document.createElement(_$[184]);//'script'
			//185: 'https://account.xiaomi.com/pass/userInfoJsonP?userId=', 186: '&callback=loginInfo.getAccountInfo'
			script.src = _$[185] + this.data.userId + _$[186];
			script.type = _$[187];//'text/javascript'
			script.async = true;//http://www.w3schools.com/tags/att_script_async.asp
			document.getElementsByTagName(_$[188])[0x0].appendChild(script);//'head'
		} else {
			this.upUserInfo();
		}
	},
	upUserInfo : function() {
		var nickName = this.data.userName;
		if (!!m.$(_$[189])) {//'LoginArea'
			//'LoginArea', '欢迎您 ', '!<a href=\'http://order.xiaomi.com/site/logout\'>退出</a>'
			m.$(_$[190]).innerHTML = _$[191] + nickName + _$[192];
			m.$(_$[193]).style.paddingLeft = _$[194];//'LoginArea', '12px'
		}
	},
//	{
//		"uniqName": "暗影萨满",
//		"miliaoInfo": {
//			"icon": "",
//			"nickName": "暗影萨满"
//		},
//		"EM": {
//			"binded": true,
//			"address": "暗影萨满@dota.com"
//		},
//		"PH": {
//			"binded": true,
//			"address": "186********"
//		},
//		"userId": 28******
//	}
	getAccountInfo : function(data) {
		if (data.userId) {
			this.data.userName = (data.uniqName) ? data.uniqName : data.userId;
			var option = {
				path : _$[195],//'/'
				domain : _$[196]//'.xiaomi.com'
			};
			m.cookie(_$[197] + this.data.userId + _$[198], this.data.userName, option);//'XM_', '_UN'
			this.upUserInfo();
		}
	}
};
function showBox(gtype) {
	if (m.cookie(_$[199])) {//'userId'
		if (gtype === _$[200]) {//'phone'
			isPhone = true;
		} else if (gtype === _$[201]) {//'box'
			isBox = true;
		}
		miphoneBuy.box(true);
		m.$(_$[202]).innerHTML = CONFIG.count;//'initCount',重置购买窗口的购买按钮的倒计时读秒
		rollInter = window.setInterval(_$[203], 0x3e8);//'Util.time()',每秒执行一次
	} else {
		location.href = _$[204];
	}
};
m.ready(function() {
	m.phone(_$[205]);//'http://p.www.xiaomi.com/m/zt/open/index.html'
	miphoneBuy.init();
	loginInfo.init();
});

 

第一步: 把超长的数组_$解码出来

我的办法是把它遍历出来之后放到textarea中,之后复制出来就好了,下面的sce.js只包含_$数组:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="sce.js"></script>
</head>
	<textarea id="pp" cols="150" rows="30"></textarea>
	<script type="text/javascript">
	for (var o in _$) {
		document.getElementById("pp").innerHTML += "'" +  _$[o].replace(/'/g, "\\'") + "\',//" + o + "\n";
	}
	</script>
</html>

 

第二步:分析代码的执行顺序和功能

执行顺序如下,功能细节见代码:

  1. m.init() >> m.doms()
  2. bindReady() >> onDOMReady()
  3. m.phone()
  4. miphoneBuy.init() >> miphoneBuy.checkCookie() >> miphoneBuy.jugeStatus(),此时开始启动定时器timeInter,每秒调用一次timeNode,直至全部售完,抢购结束!
  5. loginInfo.init()

cookie的作用如下:

  • 'xm_xt_obox' ,电视已售完
  • 'xm_xt_obox' ,电视已售完
  • 'xm_xt_pre' ,全部售完
  • 'xm_difft_hd',client和server时间差
  • 'orgin' == 'mapp',PC机登陆,否则认为是Mobile登陆

That‘s it.

分享到:
评论
3 楼 Mossad 2013-11-20  
duducs 写道
第二步是 像huangzhir以前 跳过页面等待,直接提交服务端排队 吗 

不是,我只是单纯的分析代码的执行顺序而已。
2 楼 duducs 2013-11-18  
第二步是 像huangzhir以前 跳过页面等待,直接提交服务端排队 吗 
1 楼 zrmpop 2013-11-13  
  thanks

相关推荐

    [AB PLC例程源码][MMS_044666]Translation N-A.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    kolesar_3cd_01_0716.pdf

    kolesar_3cd_01_0716

    latchman_01_0108.pdf

    latchman_01_0108

    matlab程序代码项目案例:matlab程序代码项目案例MPC在美国高速公路场景中移动的车辆上的实现.zip

    matlab程序代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    pimpinella_3cd_01_0716.pdf

    pimpinella_3cd_01_0716

    petrilla_01_0308.pdf

    petrilla_01_0308

    [AB PLC例程源码][MMS_041452]Speed Controls in Plastic Extrusion.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    强化学习驱动下DeepSeek技术创新及其对AI发展的影响

    内容概要:本文档由张卓老师讲解,重点探讨DeepSeek的技术革新及强化学习对未来AI发展的重要性。文章回顾了AI的历史与发展阶段,详细解析Transformer架构在AI上半场所起到的作用,深入介绍了MoE混合专家以及MLA低秩注意机制等技术特点如何帮助DeepSeek在AI中场建立优势,并探讨了当前强化学习的挑战和边界。文档不仅提及AlphaGo和小游戏等成功案例来说明强化学习的强大力量,还提出了关于未来人工通用智能(AGI)的展望,特别是如何利用强化学习提升现有LLMs的能力和性能。 适用人群:本资料适宜对深度学习感兴趣的研究人员、开发者以及想要深入了解人工智能最新进展的专业人士。 使用场景及目标:通过了解最新的AI技术和前沿概念,在实际工作中能够运用更先进的工具和技术解决问题。同时为那些寻求职业转型或者学术深造的人提供了宝贵的参考。 其他说明:文中提到了许多具体的例子和技术细节,如DeepSeek的技术特色、RL的理论背景等等,有助于加深读者对于现代AI系统的理解和认识。

    有师傅小程序开源版v2.4.14+前端.zip

    有师傅小程序开源版v2.4.14 新增报价短信奉告 优化部分细节

    [AB PLC例程源码][MMS_047333]Motor Sequence Starter with timers to start.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    商城二级三级分销系统(小程序+后台含源码).zip

    商城二级三级分销系统(小程序+后台含源码).zip

    li_3ck_01b_0918.pdf

    li_3ck_01b_0918

    nicholl_3cd_01_0516.pdf

    nicholl_3cd_01_0516

    1995-2022年 网络媒体关注度、报刊媒体关注度与媒体监督相关数据.zip

    媒体关注度是一个衡量公众对某个事件、话题或个体关注程度的重要指标。它主要反映了新闻媒体、社交媒体、博客等对于某一事件、话题或个体的报道和讨论程度。 媒体监督的J-F系数(Janis-Fadner系数)是一种用于测量媒体关注度的指标,特别是用于评估媒体对企业、事件或话题的监督力度。J-F系数基于媒体报道的正面和负面内容来计算,从而为公众、研究者或企业提供一个量化工具,以了解媒体对其关注的方向和强度。 本数据含原始数据、参考文献、代码do文件、最终结果。参考文献中JF系数计算公式。 指标 代码、年份、标题出现该公司的新闻总数、内容出现该公司的新闻总数、正面新闻数全部、中性新闻数全部、负面新闻数全部、正面新闻数原创、中性新闻数原创、负面新闻数原创,媒体监督JF系数。

    [AB PLC例程源码][MMS_040315]Double INC and Double DEC of INT datatype.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    [AB PLC例程源码][MMS_047773]Convert Feet to Millimeters.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    [AB PLC例程源码][MMS_042349]How to read-write data to-from a PLC using OPC in Visual Basic 6.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    matlab程序代码项目案例:matlab程序代码项目案例论文代码 多篇RMPC 鲁棒模型预测控制Paper-code-implementation.zip

    matlab程序代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    lusted_3cd_02_0716.pdf

    lusted_3cd_02_0716

    pepeljugoski_01_0107.pdf

    pepeljugoski_01_0107

Global site tag (gtag.js) - Google Analytics