首先感谢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>
第二步:分析代码的执行顺序和功能
执行顺序如下,功能细节见代码:
- m.init() >> m.doms()
- bindReady() >> onDOMReady()
- m.phone()
- miphoneBuy.init() >> miphoneBuy.checkCookie() >> miphoneBuy.jugeStatus(),此时开始启动定时器timeInter,每秒调用一次timeNode,直至全部售完,抢购结束!
- loginInfo.init()
cookie的作用如下:
- 'xm_xt_obox' ,电视已售完
- 'xm_xt_obox' ,电视已售完
- 'xm_xt_pre' ,全部售完
- 'xm_difft_hd',client和server时间差
- 'orgin' == 'mapp',PC机登陆,否则认为是Mobile登陆
That‘s it.
相关推荐
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
kolesar_3cd_01_0716
latchman_01_0108
matlab程序代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
pimpinella_3cd_01_0716
petrilla_01_0308
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
内容概要:本文档由张卓老师讲解,重点探讨DeepSeek的技术革新及强化学习对未来AI发展的重要性。文章回顾了AI的历史与发展阶段,详细解析Transformer架构在AI上半场所起到的作用,深入介绍了MoE混合专家以及MLA低秩注意机制等技术特点如何帮助DeepSeek在AI中场建立优势,并探讨了当前强化学习的挑战和边界。文档不仅提及AlphaGo和小游戏等成功案例来说明强化学习的强大力量,还提出了关于未来人工通用智能(AGI)的展望,特别是如何利用强化学习提升现有LLMs的能力和性能。 适用人群:本资料适宜对深度学习感兴趣的研究人员、开发者以及想要深入了解人工智能最新进展的专业人士。 使用场景及目标:通过了解最新的AI技术和前沿概念,在实际工作中能够运用更先进的工具和技术解决问题。同时为那些寻求职业转型或者学术深造的人提供了宝贵的参考。 其他说明:文中提到了许多具体的例子和技术细节,如DeepSeek的技术特色、RL的理论背景等等,有助于加深读者对于现代AI系统的理解和认识。
有师傅小程序开源版v2.4.14 新增报价短信奉告 优化部分细节
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
商城二级三级分销系统(小程序+后台含源码).zip
li_3ck_01b_0918
nicholl_3cd_01_0516
媒体关注度是一个衡量公众对某个事件、话题或个体关注程度的重要指标。它主要反映了新闻媒体、社交媒体、博客等对于某一事件、话题或个体的报道和讨论程度。 媒体监督的J-F系数(Janis-Fadner系数)是一种用于测量媒体关注度的指标,特别是用于评估媒体对企业、事件或话题的监督力度。J-F系数基于媒体报道的正面和负面内容来计算,从而为公众、研究者或企业提供一个量化工具,以了解媒体对其关注的方向和强度。 本数据含原始数据、参考文献、代码do文件、最终结果。参考文献中JF系数计算公式。 指标 代码、年份、标题出现该公司的新闻总数、内容出现该公司的新闻总数、正面新闻数全部、中性新闻数全部、负面新闻数全部、正面新闻数原创、中性新闻数原创、负面新闻数原创,媒体监督JF系数。
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
matlab程序代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
lusted_3cd_02_0716
pepeljugoski_01_0107