我对 Javascript 原型的扩展函数

简介: 必须事先声明,本人不赞成入侵 js 对象原型的做法。但是之所以要这样,是出于使用频率上的考虑。若不是这几个方法调用的频繁,决不会贸然加入原型里面去。 String.prototype.format 定义带标记的字符串,并用传入的字符替换标记。

必须事先声明,本人不赞成入侵 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'));

目录
相关文章
|
3月前
|
机器学习/深度学习 JavaScript 前端开发
JS进阶教程:递归函数原理与篇例解析
通过对这些代码示例的学习,我们已经了解了递归的原理以及递归在JS中的应用方法。递归虽然有着理论升华,但弄清它的核心思想并不难。举个随手可见的例子,火影鸣人做的影分身,你看到的都是同一个鸣人,但他们的行为却能在全局产生影响,这不就是递归吗?雾里看花,透过其间你或许已经深入了递归的魅力之中。
142 19
|
5月前
|
JavaScript
JS实现多条件搜索函数
JS封装的多条件搜索
|
7月前
|
JavaScript 前端开发
JavaWeb JavaScript ③ JS的流程控制和函数
通过本文的详细介绍,您可以深入理解JavaScript的流程控制和函数的使用,进而编写出高效、可维护的代码。
160 32
|
6月前
|
JavaScript 前端开发 Java
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
柯里化是一种强大的函数式编程技术,它通过将函数分解为单参数形式,实现了灵活性与可复用性的统一。无论是参数复用、延迟执行,还是函数组合,柯里化都为现代编程提供了极大的便利。 从 Redux 的选择器优化到复杂的数据流处理,再到深度嵌套的函数优化,柯里化在实际开发中展现出了非凡的价值。如果你希望编写更简洁、更优雅的代码,柯里化无疑是一个值得深入学习和实践的工具。从简单的实现到复杂的应用,希望这篇博客能为你揭开柯里化的奥秘,助力你的开发之旅! 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一
|
10月前
|
JavaScript 前端开发
JavaScript中的原型 保姆级文章一文搞懂
本文详细解析了JavaScript中的原型概念,从构造函数、原型对象、`__proto__`属性、`constructor`属性到原型链,层层递进地解释了JavaScript如何通过原型实现继承机制。适合初学者深入理解JS面向对象编程的核心原理。
157 1
JavaScript中的原型 保姆级文章一文搞懂
|
9月前
|
机器学习/深度学习 JavaScript Cloud Native
Node.js作为一种快速、可扩展的服务器端运行时环境
Node.js作为一种快速、可扩展的服务器端运行时环境
169 8
|
10月前
|
开发框架 JavaScript 前端开发
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势。通过明确的类型定义,TypeScript 能够在编码阶段发现潜在错误,提高代码质量;支持组件的清晰定义与复用,增强代码的可维护性;与 React、Vue 等框架结合,提供更佳的开发体验;适用于大型项目,优化代码结构和性能。随着 Web 技术的发展,TypeScript 的应用前景广阔,将继续引领 Web 开发的新趋势。
209 2
|
9月前
|
前端开发 JavaScript 应用服务中间件
Nginx 支持 JavaScript:前所未有的扩展
Nginx 是全球领先的高性能 Web 服务器,以其高效的反向代理和负载均衡功能著称。近期,Nginx 正式支持 JavaScript(通过 NJS 模块),基于 V8 引擎,允许在配置中嵌入 JS 代码,极大提升了灵活性和扩展性。开发者可以使用 JavaScript 实现动态请求处理、自定义认证、复杂响应处理、中间件编写及流量控制等功能,显著降低开发和维护难度,同时保持高性能。NJS 模块的引入为 Nginx 带来了前所未有的扩展能力,适应快速变化的业务需求。
232 0
|
10月前
|
前端开发 JavaScript 开发者
除了 Generator 函数,还有哪些 JavaScript 异步编程解决方案?
【10月更文挑战第30天】开发者可以根据具体的项目情况选择合适的方式来处理异步操作,以实现高效、可读和易于维护的代码。
|
11月前
|
JavaScript 前端开发
JavaScript 函数语法
JavaScript 函数是使用 `function` 关键词定义的代码块,可在调用时执行特定任务。函数可以无参或带参,参数用于传递值并在函数内部使用。函数调用可在事件触发时进行,如用户点击按钮。JavaScript 对大小写敏感,函数名和关键词必须严格匹配。示例中展示了如何通过不同参数调用函数以生成不同的输出。