扩展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 相关文章推荐
Javascript面象对象成员、共享成员变量实验
Nov 19 Javascript
JavaScript Accessor实现说明
Dec 06 Javascript
JS 退出系统并跳转到登录界面的实现代码
Jun 29 Javascript
jQuery老黄历完整实现方法
Jan 16 Javascript
JS扩展方法实例分析
Apr 15 Javascript
jquery插件treegrid树状表格的使用方法详解(.Net平台)
Jan 03 Javascript
树结构之JavaScript
Jan 24 Javascript
vue 解决addRoutes动态添加路由后刷新失效问题
Jul 02 Javascript
JS实现简易计算器
Feb 14 Javascript
vue 修改 data 数据问题并实时显示操作
Sep 07 Javascript
Vue通过阿里云oss的url连接直接下载文件并修改文件名的方法
Dec 25 Vue.js
vue实现列表垂直无缝滚动
Apr 08 Vue.js
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代码
2007/03/08 PHP
PHP基础学习之流程控制的实现分析
2013/04/28 PHP
PHP实现的登录页面信息提示功能示例
2017/07/24 PHP
javascript写的日历类(基于pj)
2010/12/28 Javascript
jQuery代码优化 遍历篇
2011/11/01 Javascript
{}与function(){}选用空对象{}来存放keyValue
2012/05/23 Javascript
javascript操作html控件实例(javascript添加html)
2013/12/02 Javascript
JavaScript通过setTimeout实时显示当前时间的方法
2015/04/16 Javascript
jQuery unbind 删除绑定事件详解
2016/05/24 Javascript
js实现获取鼠标当前的位置
2016/12/14 Javascript
AngularJS中的按需加载ocLazyLoad示例
2017/01/11 Javascript
Nodejs+Socket.io实现通讯实例代码
2017/02/13 NodeJs
JQ中$(window).load和$(document).ready区别与执行顺序
2017/03/01 Javascript
BootStrap selectpicker后台动态绑定数据的方法
2017/07/28 Javascript
JavaScript实现简单的双色球(实例讲解)
2017/07/31 Javascript
webpack external模块的具体使用
2018/03/10 Javascript
解决vue router组件状态刷新消失的问题
2018/08/01 Javascript
解决Js先触发失去焦点事件再执行点击事件的问题
2018/08/30 Javascript
微信小程序实现文件、图片上传功能
2020/08/18 Javascript
vue+ESLint 配置保存 自动格式化代码
2020/03/17 Javascript
[43:49]LGD vs CHAOS 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
python实现哈希表
2014/02/07 Python
跟老齐学Python之赋值,简单也不简单
2014/09/24 Python
Python实现识别手写数字 Python图片读入与处理
2020/03/23 Python
详解python实现识别手写MNIST数字集的程序
2018/08/03 Python
Python实现中值滤波去噪方式
2019/12/18 Python
python调用HEG工具批量处理MODIS数据的方法及注意事项
2020/02/18 Python
python 实现在shell窗口中编写print不向屏幕输出
2020/02/19 Python
python+adb命令实现自动刷视频脚本案例
2020/04/23 Python
Python 如何批量更新已安装的库
2020/05/26 Python
通过Canvas及File API缩放并上传图片完整示例
2013/08/08 HTML / CSS
Clarisonic美国官网:科莱丽声波洁面仪
2017/10/12 全球购物
上班上网检讨书
2014/01/29 职场文书
刑事申诉状范文
2015/05/20 职场文书
python实现过滤敏感词
2021/05/08 Python
Redis+AOP+自定义注解实现限流
2022/06/28 Redis