扩展JavaScript功能的正确方法(译文)


Posted in Javascript onApril 12, 2012

早上看到《JavaScript 每周导读》【第三期】一文,里面发现一篇文章(Extending JavaScript ? The Right Way),觉得还不错,翻译过来跟大家共享,本文并不是逐字逐句进行翻译,尽量说得通俗易懂。

原文地址:Extending JavaScript ? The Right Way

以下是译文

JavaScript已经内置了很多强大的方法,但有时你需要的某个功能在内置的方法中没有,我们怎么来优雅地扩展JavaScript功能呢。

例如我们想增加一个capitalize()方法来实现首字母大写,通常我们这样写:

if(!String.prototype.capitalize) 
{ 
String.prototype.capitalize = function() 
{ 
return this.slice(0,1).toUpperCase() + this.slice(1).toLowerCase(); 
} 
}

上面的代码可以正常使用,但如果在某个地方有下面的代码:

var strings = "yay"; 
for(i in strings) console.log(i + ":" + strings[i]);

我们得到的结果是这样的:
0: y
1: a
2: y
capitalize: function () { return this.slice(0, 1).toUpperCase() + this.slice(1).toLowerCase(); }

这显然不是我们想要的结果,输出了我们增加的方法的原因是我们增加的方法的enumerable属性默认为true。

我们可以通过简单地把枚举属性(enumerable)设置为false避免这个问题,使用defineProperty方法进行功能的扩展:

if(!String.prototype.capitalize) 
{ 
Object.defineProperty(String.prototype, 'capitalize', 
{ 
value: function() 
{ 
return this.slice(0,1).toUpperCase() + this.slice(1).toLowerCase(); 
}, 
enumerable: false 
}); 
}

现在我们再运行这段代码:

var strings = "yay"; 
for(i in strings) console.log(i + ":" + strings[i]);

我们得到的结果是:
0: y
1: a
2: y

要注意的是,用循环没有输出的并不代表不存在,我们可以通过下面的代码查看到定义:

var strings = "yay"; 
console.log(strings.capitalize)

会输出:

function () { return this.slice(0, 1).toUpperCase() + this.slice(1).toLowerCase(); }

用这种方式扩展JavaScript功能比较灵活,我们可以用这种方式来定义我们自己的对象,并设置一些默认值。

以下是另外几个扩展方法,你可以在自己的项目中使用:

String.pxToInt()

把"200px"这样的字符串转换为数字 200 :

if(!String.prototype.pxToInt) 
{ 
Object.defineProperty(String.prototype, 'pxToInt', 
{ 
value: function() 
{ 
return parseInt(this.split('px')[0]); 
}, 
enumerable: false 
}); 
}

String.isHex()

判断一个字符串是否是16进制表示的,如"#CCC" 或 "#CACACA"

if(!String.prototype.isHex) 
{ 
Object.defineProperty(String.prototype, 'isHex', 
{ 
value: function() 
{ 
return this.substring(0,1) == '#' && 
(this.length == 4 || this.length == 7) && 
/^[0-9a-fA-F]+$/.test(this.slice(1)); 
}, 
enumerable: false 
}); 
}

String.reverse()

字符串反转:

if(!String.prototype.reverse) 
{ 
Object.defineProperty(String.prototype, 'reverse', 
{ 
value: function() 
{ 
return this.split( '' ).reverse().join( '' ); 
}, 
enumerable: false 
}); 
}

String.wordCount()

统计单词数量,用空格分开

if(!String.prototype.wordCount) 
{ 
Object.defineProperty(String.prototype, 'wordCount', 
{ 
value: function() 
{ 
return this.split(' ').length; 
}, 
enumerable: false 
}); 
}

String.htmlEntities()

html标签如<和>编码为特殊字符

if(!String.prototype.htmlEntities) 
{ 
Object.defineProperty(String.prototype, 'htmlEntities', 
{ 
value: function() 
{ 
return String(this).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); 
}, 
enumerable: false 
}); 
}

String.stripTags()

去掉HTML标签:

if(!String.prototype.stripTags) 
{ 
Object.defineProperty(String.prototype, 'stripTags', 
{ 
value: function() 
{ 
return this.replace(/<\/?[^>]+>/gi, ''); 
}, 
enumerable: false 
}); 
}

String.trim()

去掉首尾空格:

if(!String.prototype.trim) 
{ 
Object.defineProperty(String.prototype, 'trim', 
{ 
value: function() 
{ 
return this.replace(/^\s*/, "").replace(/\s*$/, ""); 
}, 
enumerable: false 
}); 
}

String.stripNonAlpha()

去掉非字母字符:

if(!String.prototype.stripNonAlpha) 
{ 
Object.defineProperty(String.prototype, 'stripNonAlpha', 
{ 
value: function() 
{ 
return this.replace(/[^A-Za-z ]+/g, ""); 
}, 
enumerable: false 
}); 
}

Object.sizeof()

统计对象的大小,如{one: “and”, two: “and”}为2

if(!Object.prototype.sizeof) 
{ 
Object.defineProperty(Object.prototype, 'sizeof', 
{ 
value: function() 
{ 
var counter = 0; 
for(index in this) counter++; 
return counter; 
}, 
enumerable: false 
}); 
}

这种方式扩展JS原生对象的功能还是挺不错的,但除非必要(项目中用的很多),不建议直接在原生对象上扩展功能,会造成全局变量污染。

另外,文中的pxToInt()方法是没什么必要的,JS中的parseInt()可以直接完成这样的功能:parsetInt("200px")===200

htmlEntities方法貌似有问题,下面另提供一个:

if(!String.prototype.htmlEntities) 
{ 
Object.defineProperty(String.prototype, 'htmlEntities', 
{ 
value: function() 
{ 
var div = document.createElement("div"); 
if(div.textContent){ 
div.textContent=this; 
} 
else{ 
div.innerText=this; 
} 
return div.innerHTML; 
}, 
enumerable: false 
}); 
}
Javascript 相关文章推荐
juqery 学习之三 选择器 简单 内容
Nov 25 Javascript
JavaScript字符串String和Array操作的有趣方法
Dec 18 Javascript
JS实现点击下载的小例子
Jul 10 Javascript
jQuery制作仿腾讯web qq用户体验桌面
Aug 20 Javascript
jQuery实现仿腾讯微博滑出效果报告每日天气的方法
May 11 Javascript
jQuery实现的五子棋游戏实例
Jun 13 Javascript
jQuery实现可高亮显示的二级CSS菜单效果
Sep 01 Javascript
解决js函数闭包内存泄露问题的办法
Jan 25 Javascript
解决jquery无法找到其他父级子集问题的方法
May 10 Javascript
JS异步文件分片断点上传的实现思路
Dec 25 Javascript
JavaScript数组_动力节点Java学院整理
Jun 26 Javascript
jquery实现Ajax请求的几种常见方式总结
May 28 jQuery
idTabs基于JQuery的根据URL参数选择Tab插件
Apr 11 #Javascript
JQuery学习笔录 简单的JQuery
Apr 09 #Javascript
广泛收集的jQuery拖放插件集合
Apr 09 #Javascript
深入分析js中的constructor和prototype
Apr 07 #Javascript
浅谈javascript中的作用域
Apr 07 #Javascript
JavaScript 高级篇之DOM文档,简单封装及调用、动态添加、删除样式(六)
Apr 07 #Javascript
JavaScript 高级篇之闭包、模拟类,继承(五)
Apr 07 #Javascript
You might like
基于PHP代码实现中奖概率算法可用于刮刮卡、大转盘等抽奖算法
2015/12/20 PHP
php preg_match的匹配不同国家语言实例
2016/12/29 PHP
ie 调试javascript的工具
2009/04/29 Javascript
javascript 冒号 使用说明
2009/06/06 Javascript
JQuery优缺点分析说明
2010/06/09 Javascript
IE下使用cloneNode注意事项分享
2012/11/22 Javascript
javascript中的变量作用域以及变量提升详细介绍
2013/10/24 Javascript
浅谈Javascript中深复制
2014/12/01 Javascript
node.js解决获取图片真实文件类型的问题
2014/12/20 Javascript
探究Vue.js 2.0新增的虚拟DOM
2016/10/20 Javascript
基于JavaScript实现弹幕特效
2020/08/27 Javascript
react-navigation 如何判断用户是否登录跳转到登录页的方法
2017/12/01 Javascript
angular基于ng-alain定义自己的select组件示例
2018/02/23 Javascript
浅谈AngularJS中$http服务的简单用法
2018/05/15 Javascript
JS中验证整数和小数的正则表达式
2018/10/08 Javascript
JQueryDOM之样式操作
2019/03/27 jQuery
vue使用vuex实现首页导航切换不同路由的方法
2019/05/08 Javascript
在node环境下parse Smarty模板的使用示例代码
2019/11/15 Javascript
JavaScript 几种循环方式以及模块化的总结
2020/09/03 Javascript
Python对两个有序列表进行合并和排序的例子
2014/06/13 Python
在Django框架中伪造捕捉到的URLconf值的方法
2015/07/18 Python
详解MySQL数据类型int(M)中M的含义
2016/11/20 Python
Python中functools模块函数解析
2017/03/12 Python
Python-copy()与deepcopy()区别详解
2019/07/12 Python
pandas如何处理缺失值
2019/07/31 Python
Django模板之基本的 for 循环 和 List内容的显示方式
2020/03/31 Python
使用python编写一个语音朗读闹钟功能的示例代码
2020/07/14 Python
俄罗斯花园种植材料批发和零售网上商店:Беккер
2019/07/22 全球购物
匈牙利超级网上商店和优惠:Alza.hu
2019/12/17 全球购物
Boolean b = new Boolean(“abcde”); 会编译错误码
2013/11/27 面试题
会计电算化应届生求职信
2013/11/03 职场文书
记账会计岗位职责
2014/06/16 职场文书
生产工厂门卫岗位职责
2014/09/26 职场文书
2015年教师节感恩寄语
2015/03/23 职场文书
趣味运动会通讯稿
2015/07/18 职场文书
2015年乡镇食品安全工作总结
2015/10/22 职场文书