JS方法代理
来源:互联网 发布:企业怎样做网络推广 编辑:程序博客网 时间:2024/06/08 19:14
作者:Jiang, Jilin
JS作为一门脚本语言,十分容易上手。外加其灵活性,可以轻而易举地扩展功能。今天,我们就聊聊JS的方法代理。方法代理是脚本语言中常见的方法扩展形式。这种灵活的形式优点在于遇到复杂的JS代码需要扩展时,可以相对简单的抽取并修改。但是,其缺点也十分明显,会造成代码的碎片化,因而是一把双刃剑。
基本形式
var _func = obj.func;
obj.func = function() {
return _func();
};
此处,obj的func方法是原始方法。我们使用一个_func变量保存该方法,之后重写func方法,返回调用原始的方法。相当的好理解。
不定长参数
有时候,我们会遇到不定长参数的形式。那么我们可以做以下更改:
var _func = obj.func;
obj.func = function() {
return _func.apply(this, arguments);
};
写到这里,JS方法代理的两种形式已经写完了。这时,你可能会疑惑这种方法代理有什么用?那么,就跟随我看看几个例子吧:
重写静态方法
出于某些原因,我们需要在console打印的同时,将打印数据传输到指定服务器上用户帮助统计数据。而在开发过程中,直接使用了原生态的console.log方法输出。那么,我们就可做如下修改。
首先,构建代理方法:
var _log = console.log;
console.log = function() {
return _log.apply(this, arguments);
};
接着,插入ajax调用逻辑:
console.log = function() {
var _args = Array.prototype.slice.call(arguments);
$.post("srvAddr", {userID: userID, args: _args});
return _log.apply(this, arguments);
};
可以很容易预见效果:
原型代理
有时候,我们需要直接接管一个类的方法。那么相应的,我们就要将其prototype中的方法做代理。现在我们假设要使得Array默认支持数字排序:
var _sort = Array.prototype.sort;
Array.prototype.sort = function() {
_sort.apply(this, arguments);
};
我们首先检测数组中的元素是否是数字,如果是则按照数字排序,否则就按照默认方式排序:
var _sort = Array.prototype.sort;
Array.prototype.sort = function() {
var _isNum = true;
for(var i = 0 ; i < this.length ; i += 1) {
if(typeof this[i] !== "number") {
_isNum = false;
break;
}
}
if(_isNum) {
return _sort.call(this, function(a, b) {
return a - b;
});
} else {
return _sort.apply(this, arguments);
}
};
原始排序方式(将数字转换成字符排序)
代理后排序方式
注意:此处仅作为原型方法代理的例子。在实际开发中,应该尽量避免对原生对象原型方法做代理。
重载
在jQuery中,toggle方法拥有多种重载,其中一个为toggle(display),通过接受boolean参数来决定元素显示还是隐藏。而fadeToggle方法则不接受该参数。让我们进行简单的代理,使其支持boolean参数:
var _fadeToggle = $.fn.fadeToggle;
$.fn.fadeToggle = function(display) {
if(arguments.length === 1 && typeof display === "boolean") {
if(display) {
return this.fadeIn();
} else {
return this.fadeOut();
}
}
return _fadeToggle.apply(this, arguments);
};
通过参数长度和接收参数类型类型判断是否调用fadeIn或fadeOut方法。如果不匹配则调用原来的fadeToggle方法。以此类推,slideToggle也可以同样适用。
*继承
继承中,我们有时候会需要调用父类方法来实现。这和java中的super有些类似。一个简单的例子。我们定义了一个Person,可以laugh。同时定义一个Robot继承,是其沿用Person的laugh但是稍作修改:
var Person = function() {
this.name = "";
this.laugh = function() {
return "Ha ha!";
};
return this;
};
var Robot = function() {
Person.apply(this);
var _laugh = this.laugh;
this.laugh = function() {
return encodeURIComponent(_laugh());
};
return this;
};
劫持
说到劫持,则和安全性开始挂钩了。如今大多数网站都习惯于使用开源的js库来开发,但是如果碰巧被插入了恶意代码,那么安全也就变得不安全了(例如chrome中大量未经验证的游览器插件)。以下,我们将举几个劫持的例子。
Ajax劫持
不少人以为,通过闭包的方式将重要用户参数存储在作用域内(例如动态生成的secureID),那么即便是被插入了恶意代码也无法获取到,从而无法伪造ajax请求来获取重要信息似乎就足够了。但是如果整个ajax请求被拦截了呢?
var _ajax = $.ajax;
$.ajax = function() {
var $p = _ajax.apply($, arguments);
$p.done(function(data) {
// Do something...
});
return $p;
};
jQuery中所有ajax请求(get,post,getJSON)最终都会调用$.ajax来实现。而通过方法代理直接劫持$.ajax方法并返回一个正常promise对象,会使得页面脚本运行毫无影响。但是实际上数据已经被劫持走了。
Array劫持
Array拥有不少原型方法,例如push,pop,shift,unshift等等。我们只需要简单的代理数组操作方法,便可以截获数据。
var _push = Array.prototype.push;
Array.prototype.push = function() {
// Do something...
return _push.apply(this, arguments);
};
好了,以上就是这次的方法代理介绍。由于方法代理会混乱代码逻辑使得代码结构变得不易理解。在日常开发过程中,我们应该尽量避免使用它。只有在代理重载,或者更改难以理解的遗留代码的部分逻辑时使用它。从而避免将双刃剑误伤了自己。
- JS方法代理
- JS方法代理
- 原生js 事件代理方法
- JS跨域问题解决方法之APACHE反向代理
- Js中通过Ajax调用代理的方法
- JS获取浏览器UA(User Agent 用户代理)方法
- JS和Native交互之 -UIWebView的代理方法
- JS获取浏览器UA(User Agent 用户代理)方法
- js代理模式-代理事件
- node.js代理设置
- 代理解决js跨域
- js事件代理
- JS事件代理
- JS中的事件代理
- js事件代理
- JS事件代理
- js-事件代理
- js事件代理
- 统计数据库所有表的字段之和
- Cocos2dx 3.0 以上版本 集成 MFC
- C#调用WPS的两种方式
- 【二十】二叉树及其性质
- JAVA书籍
- JS方法代理
- mac系统如何显示和隐藏文件
- leetcode:Container With Most Water 6行AC
- Qt Creater调试时一直出现:“DEBUGGER: Waiting for debug socket connect” 和“DEBUGGER: go to sleep”
- Hibernate封装通用数据操作基类DAO
- vs中使用qt的qrc生成rcc资源文件
- JAVA_Proxy_DEMO
- 数据库模型
- 报表示例——用Jasper report实现MongoDB join