一、最有效高效、却最不被看得起的 抄袭、说好听-保留一份随时用。
人家的思维:
Ajax拦截器的实现。
个人觉得编程和下棋类似,卡位非常重要。一开始占据着有利的位置,当你在面对变化的时候就会非常灵活。编程中的卡位就是将一些关键的地方预留好,方便以后扩展。比如前端开发中的全局的事件代理,核心组件的基类设计,ajax拦截器等。
最近在做一个ajax加密的需求,就是所有ajax请求的参数都需要经过加密,防止他人盗用api。如果有ajax拦截器,这个需求实现会非常简单,只需要在拦截器里面实现加密即可。第一期,我们利用前端框架本身的ajax拦截器,完成了http加密,一切都很顺利。后续的第二期则遇个麻烦事情,我们需要对所有的前端工程(webvie、管理后台、活动…)进行加密,这些工程都是独立工程,而且使用的框架也不太一样。这就意味着我们第一期的加密代码很难被重用。
怎么办?我们想到了从更底层的XMLHttpRequest上去做文章,如果能在这层做掉,则和上层使用的框架无关了。即使跨越多个工程,也可以使用同一套加密方法。
经过调研window.XMLHttpRequest是可以被覆盖的。如果我们能包装一个和XMLHttpRequest一摸一样的构造器来覆盖原有的,则问题就解决了。经调研,几乎所有前端框架或库在做ajax特性检测时,会首先尝试使用XMLHttpRequest。那么在ie下,我们也可以将ActiveXObject包装成一个XMLHttpRequest。
该实现已经作为一个开源的小js库发布了。浏览器可以兼容到ie6+,若有类似的需求可以直接使用。代码总共不到200行,详情可以戳 https://github.com/vinnyguitar/xhr-overwrite。欢迎一起讨论,改进。
人家的代码:就这么几行就是插件了。并且实用、底层、高效。
var overwriteXhr = function () {
function t(t, e, s) {
for (var n in t) try {
e.call(s, t[n], n, t)
} catch (o) {}
}
function e(t, e, s) {
for (var n = 0; n < t.length; n++) e.call(s, t[n], n)
}
function s(t) {
return "[object function]" == Object.prototype.toString.call(t).toLowerCase()
}
function n() {
if (c) return new c;
for (var t = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Msxml2.XMLHTTP.4.0", "Msxml2.XMLHTTP.5.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"], e = 0; e < t.length; e++) try {
return new ActiveXObject(t[e])
} catch (s) {}
}
var o = /^on[a-z]+$/,
r = /^[A-Z]+$/,
i = {
config: 1,
status: 2,
method: 3,
callback: 4,
constant: 5
},
a = {
timeout: i.config,
withCredentials: i.config,
readyState: i.status,
response: i.status,
responseText: i.status,
responseBody: i.status,
responseType: i.status,
responseURL: i.status,
responseXML: i.status,
status: i.status,
statusText: i.status,
abort: i.method,
getAllResponseHeaders: i.method,
getResponseHeader: i.method,
open: i.method,
send: i.method,
setRequestHeader: i.method,
onreadystatechange: i.callback,
ontimeout: i.callback
},
c = window.XMLHttpRequest;
return function (c) {
function u() {
var h = n(),
f = [],
d = [],
l = {};
this.xhr = h, this.constructor = u;
for (var p in a) a.hasOwnProperty(p) && (l[p] = a[p]);
t(h, function (t, e) {
this[e] || (r.test(e) && "undefined" != typeof t ? this[e] = i.constant : s(t) && !o.test(e) ? this[e] = i.method : o.test(e) && null === t ? this[e] = i.callback : this[e] = i.config)
}, l), t(l, function (t, e) {
t === i.config ? f.push(e) : t === i.status && d.push(e)
}), t(c, function (t, e) {
s(t) && (this[e] = t)
}, this), t(l, function (t, n) {
try {
var o = h[n]
} catch (r) {}
if (!(void 0 === o && !n in a)) switch (t) {
case i.constant:
this[n] = o;
break;
case i.method:
if (this[n] || ("setRequestHeader" === n ? this.setRequestHeader = function (t, e) {
return h.setRequestHeader(t, e)
} : "send" === n ? this.send = function (t) {
return h.send(t)
} : "open" === n ? this.open = function (t, e, s, n, o) {
return h.open(t, e, s, n, o)
} : n in a ? this[n] = function () {
return h[n]()
} : this[n] = function () {
return h[n](arguments[0], arguments[1])
}), "send" === n) {
var c = this.send;
this.send = function () {
return e(f, function (t) {
try {
h[t] = this[t]
} catch (e) {}
}, this), c.apply(this, arguments)
}
}
break;
case i.callback:
var u = this;
h[n] = function () {
e(d, function (t) {
try {
u[t] = h[t]
} catch (e) {}
}), s(u[n]) && u[n]()
}
}
}, this)
}
c && (window.XMLHttpRequest = u)
}
}();
"object" == typeof module && "object" == typeof module.exports && (module.exports = overwriteXhr);