扩展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下关于$.Ready()的分析
Dec 13 Javascript
js操作ajax返回的json的注意问题!
Feb 23 Javascript
jquery ajax 同步异步的执行 return值不能取得的解决方案
Jan 08 Javascript
js 操作select和option常用代码整理
Dec 13 Javascript
Js实现网页键盘控制翻页的方法
Oct 30 Javascript
JavaScript实现网页对象拖放功能的方法
Apr 15 Javascript
JavaScript之cookie技术详解
Nov 18 Javascript
Vue封装一个简单轻量的上传文件组件的示例
Mar 21 Javascript
浅谈node中的cluster集群
Jun 02 Javascript
微信小程序实现人脸识别登陆的示例代码
Apr 02 Javascript
vue 检测用户上传图片宽高的方法
Feb 06 Javascript
微信分享invalid signature签名错误踩过的坑
Apr 11 Javascript
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
一个很方便的 XML 类!!原创的噢
2006/10/09 PHP
用PHP实现将GB编码转换为UTF8
2006/11/25 PHP
php计划任务之ignore_user_abort函数实现方法
2015/01/08 PHP
php将图片文件转换成二进制输出的方法
2015/06/10 PHP
Cygwin中安装PHP方法步骤
2015/07/04 PHP
tp5.0框架隐藏index.php入口文件及模块和控制器的方法分析
2020/02/11 PHP
jQuery关于导航条背景切换效果实现示例
2013/09/04 Javascript
jquery $(this).attr $(this).val方法使用介绍
2013/10/08 Javascript
Jquery中的层次选择器与find()的区别示例介绍
2014/02/20 Javascript
js返回上一页并刷新的多种实现方法
2014/02/26 Javascript
jquery ztree实现下拉树形框使用到了json数据
2014/05/14 Javascript
JavaScript中遍历对象的property的3种方法介绍
2014/12/30 Javascript
浅谈JavaScript中的String对象常用方法
2015/02/25 Javascript
JavaScript使ifram跨域相互访问及与PHP通信的实例
2016/03/03 Javascript
深入理解JavaScript中为什么string可以拥有方法
2016/05/24 Javascript
Angularjs实现带查找筛选功能的select下拉框示例代码
2016/10/04 Javascript
微信小程序 for 循环详解
2016/10/09 Javascript
浅谈MVC+EF easyui dataGrid 动态加载分页表格
2016/11/10 Javascript
jQuery与JavaScript节点创建方法的对比
2016/11/18 Javascript
JavaScript自定义文本框光标
2017/03/05 Javascript
React从react-router路由上做登陆验证控制的方法
2018/05/10 Javascript
详解使用VueJS开发项目中的兼容问题
2018/08/02 Javascript
Node.js Koa2使用JWT进行鉴权的方法示例
2018/08/17 Javascript
Vue 通过公共字段,拼接两个对象数组的实例
2019/11/07 Javascript
微信小程序监听用户登录事件的实现方法
2019/11/11 Javascript
Vue3 响应式侦听与计算的实现
2020/11/11 Javascript
PyQt实现界面翻转切换效果
2018/04/20 Python
django初始化数据库的实例
2018/05/27 Python
Python实现E-Mail收集插件实例教程
2019/02/06 Python
Python Pandas 获取列匹配特定值的行的索引问题
2019/07/01 Python
利用pipenv和pyenv管理多个相互独立的Python虚拟开发环境
2020/11/01 Python
一款利用纯css3实现的超炫3D表单的实例教程
2014/12/01 HTML / CSS
描述RIP和OSPF区别以及特点
2015/01/17 面试题
公务员平时考核实施方案
2014/03/11 职场文书
优秀团员事迹材料1500字
2014/08/31 职场文书
一篇文章告诉你如何实现Vue前端分页和后端分页
2022/02/18 Vue.js