扩展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 相关文章推荐
jQuery的三种$()
Dec 30 Javascript
Jquery同辈元素选中/未选中效果的实例代码
Aug 01 Javascript
Markdown与Bootstrap相结合实现图片自适应属性
May 04 Javascript
设置jQueryUI DatePicker默认语言为中文
Jun 04 Javascript
使用jQuery的ajax方法向服务器发出get和post请求的方法
Jan 13 Javascript
JS实现经典的中国地区三级联动下拉菜单功能实例【测试可用】
Jun 06 Javascript
package.json文件配置详解
Jun 15 Javascript
JS中将多个逗号替换为一个逗号的实现代码
Jun 23 Javascript
在react中使用vuex的示例代码
Jul 30 Javascript
Element图表初始大小及窗口自适应实现
Jul 10 Javascript
从表单校验看JavaScript策略模式的使用详解
Oct 17 Javascript
vue+iview分页组件的封装
Nov 17 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
CodeIgniter实现从网站抓取图片并自动下载到文件夹里的方法
2015/06/17 PHP
PHP环形链表实现方法示例
2017/09/15 PHP
JavaScript 原型继承
2011/12/26 Javascript
js中scrollHeight,scrollWidth,scrollLeft,scrolltop等差别介绍
2012/05/16 Javascript
JS中把字符转成ASCII值的函数示例代码
2013/11/21 Javascript
Angular Js文件上传之form-data
2015/08/28 Javascript
jQuery实现气球弹出框式的侧边导航菜单效果
2015/09/22 Javascript
使用Sticky组件实现带sticky效果的tab导航和滚动导航的方法
2016/03/22 Javascript
谈一谈bootstrap响应式布局
2016/05/23 Javascript
利用Js的console对象,在控制台打印调式信息测试Js的实现
2016/11/26 Javascript
JS中input表单隐藏域及其使用方法
2017/02/13 Javascript
详谈js使用in和hasOwnProperty获取对象属性的区别
2017/04/25 Javascript
如何通过setTimeout理解JS运行机制详解
2019/03/23 Javascript
详解vue的数据劫持以及操作数组的坑
2019/04/18 Javascript
Angular如何由模板生成DOM树的方法
2019/12/23 Javascript
[01:07:53]RNG vs VG 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
使用PYTHON创建XML文档
2012/03/01 Python
Python性能优化技巧
2015/03/09 Python
在Python中操作字典之update()方法的使用
2015/05/22 Python
深入浅析python定时杀进程
2016/06/06 Python
python使用代理ip访问网站的实例
2018/05/07 Python
python2.7和NLTK安装详细教程
2018/09/19 Python
Python实现栈的方法详解【基于数组和单链表两种方法】
2020/02/22 Python
python 实现在无序数组中找到中位数方法
2020/03/03 Python
解决更改AUTH_USER_MODEL后出现的问题
2020/05/14 Python
Python数据可视化实现漏斗图过程图解
2020/07/20 Python
Python模块常用四种安装方式
2020/10/20 Python
美国婴儿用品店:Babies”R”Us
2017/10/12 全球购物
会计电算化专业个人的自我评价
2013/11/24 职场文书
大学生学习2014全国两会心得体会
2014/03/13 职场文书
工作业绩不及格检讨书
2014/10/28 职场文书
社区法制宣传日活动总结
2015/05/05 职场文书
2015年小学图书室工作总结
2015/05/18 职场文书
学会掌握自己命运的十条黄金法则:
2019/08/08 职场文书
如何使用PyCharm及常用配置详解
2021/06/03 Python
关于MySQL中explain工具的使用
2023/05/08 MySQL