• JS方法代理


    作者:Jiang, Jilin

    JS作为一门脚本语言。十分easy上手。外加其灵活性,能够轻而易举地扩展功能。今天,我们就聊聊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打印的同一时候,将打印传输数据到指定server上用户帮助统计数据。而在开发过程中,直接使用了原生态的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);

    };

    能够非常easy预见效果:



    原型代理

    有时候,我们须要直接接管一个类的方法。

    那么对应的。我们就要将其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);

    };

    好了,以上就是这次的方法代理介绍。因为方法代理会混乱代码逻辑使得代码结构变得不易理解。

    在日常开发过程中,我们应该尽量避免使用它。仅仅有在代理重载,或者更改难以理解的遗留代码的部分逻辑时使用它。

    从而避免将双刃剑误伤了自己。


  • 相关阅读:
    Delphi从Internet下载文件
    datasnap 上传/下载大文件(本Demo以图传片文件为例)
    delphi 理解ParamStr
    delphi2010多线程编程教程
    QQ2008自动聊天精灵delphi源码
    Delphi使用Indy、ICS组件读取网页
    UniDac 使用日记(转)
    delphi xe5 安卓 配置sqlite
    Netty内存管理器ByteBufAllocator及内存分配
    初识内存分配ByteBuf
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/6755254.html
Copyright © 2020-2023  润新知