我對 Javascript 原型的擴充函數

來源:互聯網
上載者:User
文章目錄
  • String.prototype.format
  • Date.prototype.format
  • Function.prototype.delegate
  • 碉堡了!

必須事先聲明,本人不贊成入侵 js 對象原型的做法。但是之所以要這樣,是出於使用頻率上的考慮。若不是這幾個方法調用的頻繁,決不會貿然加入原型裡面去。

String.prototype.format定義帶標記的字串,並用傳入的字元替換標記。每個標記必須是唯一的,而且必須要像{0},{1}...{n}這樣地自增長。例如:
var cls = 'my-class', text = 'Some text';var s = String.format('<div class="{0}">{1}</div>', cls, text);//s現在是字串:s now contains the string: '<div class="my-class">Some text</div>'

String.prototype.format 源碼如下(該方法應用了“函數自覆蓋模式”,參見我以往文章《函數自覆蓋模式》介紹):

/** * 格式化字串。 * @param  {String} string 帶標記的字串,或者可變長度的字串參數。 * @param  {String} value1 第一個值,替換{0}。The value to replace token {0} * @param  {String} value2 第二個值,替換{1}...等等(可以有任意多個)。Etc... * @return {String} 轉化過的字串。The formatted string */String.prototype.format = function () {    var regexp = /{(\d+)}/g, replace = String.prototype.replace;    function replaceEl(m, i) {        return this[i]; // this為arguments    }    /* At first run, with override it. */    var fn = String.prototype.format = function () {        replaceEl.scope = arguments; // 委託範圍        return replace.call(this, regexp, replaceEl.delegate());    }    return fn.apply(this, arguments); // first run}
Date.prototype.format

日期格式化。詳見我以往部落格文章:《JavaScript自訂日期格式化函數》http://blog.csdn.net/zhangxin09/archive/2011/01/01/6111294.aspx 例子:

alert(new Date().format("yyyy-MM-dd hh:mm:ss"));

Date.prototype.format 源碼如下:

/** * 日期格式化 * @param {String} format * @return{String}*/Date.prototype.format = function (format) {    var $1, o = {        "M+": this.getMonth() + 1,// 月份,從0開始算        "d+": this.getDate(),   // 日期        "h+": this.getHours(),   // 小時        "m+": this.getMinutes(), // 分鐘        "s+": this.getSeconds(), // 秒鐘        // 季度 quarter        "q+": Math.floor((this.getMonth() + 3) / 3),        "S": this.getMilliseconds()// 千秒    };    var key, value;    if (/(y+)/.test(format)) {        $1 = RegExp.$1,         format = format.replace($1, String(this.getFullYear()).substr(4 - $1));    }    for (key in o) { // 如果沒有指定該參數,則子字串將延續到 stringvar 的最後。        if (new RegExp("(" + key + ")").test(format)) {            $1= RegExp.$1,    value= String(o[key]),    value= $1.length == 1 ? value : ("00" + value).substr(value.length),    format= format.replace($1, value);        }    }    return format;}
Function.prototype.delegate

delegate() 即是委派的意思,Function.prototype.delegate() 就是函數的委託。delegate 方法字在我所使用的庫中應用廣泛,大體可以分為兩個地方的使用,即在函數的參數中使用和在函數的範圍中使用。後者指的是封裝對象(this或者環繞閉包)。delegate 方法可以使得函數的 this 指標改變。預設函數的範圍。考查下面兩個方法:

Function.prototype.delegateScope = function (scope){var self = this;return function(){return self.apply(scope, arguments);}}Function.prototype.delegateArgs = function(){var self  = this, args = arguments;    return function(){return self.apply(this, args);};}

Function.prototype.delegate 源碼如下(另有 after 方法,比較簡單,請看源碼):

/*** 函數委託 force Args! so there's no args, it server as Args!* @return {Function}*/Function.prototype.delegate = function () {    var self = this, scope = this.scope, args = arguments, aLength = arguments.length, fnToken = 'function';    return function () {        var      bLength = arguments.length    , Length = (aLength > bLength) ? aLength : bLength;        // mission one:        for (var i = 0; i < Length; i++) {            if (arguments[i]) {                args[i] = arguments[i]; // 拷貝參數            }        }        args.length = Length; // 在 MS jscript下面,arguments作為數字來使用還是有問題,就是length不能自動更新。修正如左:        // mission two:        for (var i = 0, j = args.length; i < j; i++) {            var _arg = args[i];            if (_arg && typeof _arg == fnToken && _arg.late == true) {                args[i] = _arg.apply(scope || this, args);            }        }        return self.apply(scope || this, args);    };}if (!Function.prototype.bind) {    Function.prototype.bind = function (scope) {        this.scope = scope;        return this.delegate();    }}/*** 設定一個後置函數。* @param  {Function} composeFn* @param  {Boolean}  isForceCall 是否強行執行 call 方法。設定為 true 在數組作為單獨對象的時候有用。* @return {Function}*/Function.prototype.after = function (composeFn, isForceCall, scope) {    var self = this;    return function () {        var result = self.apply(scope || this, arguments);        if (isForceCall) {            return composeFn.call(this, result);        }        return result && (typeof result.pop != 'undefined') && (typeof result.pop != 'unknown')     ? composeFn.apply(this, result)     : composeFn.call(this, result);    };}
碉堡了!

有次使用 String.prototype.format,發現它要依賴 Function.prototype.delegate,而且又閉包、又正則什麼亂七八糟的,十分累的說。於是上網搜尋更好的方案,起初是抱著試試看的心態,沒想發現一個極其簡潔的思路!十分自然而且效率高。回想之前搞的,可能也是從這麼簡單開始的,但越走越後,卻走火入魔了,到現在真是“反人類的”。

String.prototype.format = function () {var str = this; for(var i = 0, j = arguments.length; i < j; i++){str = str.replace(new RegExp('\\{' + i +'\\}', 'g'), arguments[i]);}return str;}console.log('hihih {0}, ,{2}'.format('dfasda', '34324343','dffds34324'));

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.