扩展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 相关文章推荐
用htc组件制作windows选项卡
Jan 13 Javascript
使用GruntJS链接与压缩多个JavaScript文件过程详解
Aug 02 Javascript
判断字符串的长度(优化版)中文占两个字符
Oct 30 Javascript
jQuery实现灰蓝风格标准二级下拉菜单效果代码
Aug 31 Javascript
原生JS和jQuery版实现文件上传功能
Apr 18 Javascript
原生js实现手风琴功能(支持横纵向调用)
Jan 13 Javascript
浅谈angularjs $http提交数据探索
Jan 20 Javascript
jQuery EasyUI之验证框validatebox实例详解
Apr 10 jQuery
js实现可以点击收缩或张开的悬浮窗
Sep 18 Javascript
vue2.0 better-scroll 实现移动端滑动的示例代码
Jan 25 Javascript
使用mint-ui实现省市区三级联动效果的示例代码
Feb 09 Javascript
Vue不能观察到数组length的变化
Jun 08 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
德生S2000电路分析
2021/03/02 无线电
php fsockopen伪造post与get方法的详解
2013/06/14 PHP
PHP垃圾回收机制引用计数器概念分析
2013/06/24 PHP
destoon二次开发常用数据库操作
2014/06/21 PHP
PHP 正则表达式小结
2015/02/12 PHP
Discuz!X中SESSION机制实例详解
2015/09/23 PHP
Zend Framework分页类用法详解
2016/03/22 PHP
PDO::exec讲解
2019/01/28 PHP
YII框架http缓存操作示例
2019/04/29 PHP
js异或加解密效果代码
2008/06/25 Javascript
(jQuery,mootools,dojo)使用适合自己的编程别名命名
2010/09/14 Javascript
js或者jquery判断图片是否加载完成实现代码
2013/03/20 Javascript
jQuery文本框(input textare)事件绑定方法教程
2013/04/24 Javascript
JS实现跟随鼠标立体翻转图片的方法
2015/05/04 Javascript
JS实现六边形3D拖拽翻转效果的方法
2016/09/11 Javascript
Javascript数组中push方法用法分析
2016/10/31 Javascript
Vue基于NUXT的SSR详解
2017/10/24 Javascript
Vue2.0 axios前后端登陆拦截器(实例讲解)
2017/10/27 Javascript
vue2.5.2使用http请求获取静态json数据的实例代码
2018/02/27 Javascript
Vue v-text指令简单使用方法示例
2019/09/19 Javascript
vue项目中锚点定位替代方式
2019/11/13 Javascript
JS中this的4种绑定规则详解
2020/02/04 Javascript
JS运算符优先级与表达式示例详解
2020/09/04 Javascript
剖析Python的Tornado框架中session支持的实现代码
2015/08/21 Python
Python实现按中文排序的方法示例
2018/04/25 Python
python config文件的读写操作示例
2019/09/27 Python
Python+Tensorflow+CNN实现车牌识别的示例代码
2019/10/11 Python
解决reload(sys)后print失效的问题
2020/04/25 Python
Python 分布式缓存之Reids数据类型操作详解
2020/06/24 Python
Python必须了解的35个关键词
2020/07/16 Python
别名指示符是什么
2012/10/08 面试题
30年同学聚会感言
2014/01/30 职场文书
党的群众路线教育实践活动领导班子整改措施
2014/09/30 职场文书
工厂门卫岗位职责
2015/04/13 职场文书
个人工作失误的保证书怎么写?
2019/06/21 职场文书
my.ini优化mysql数据库性能的十个参数(推荐)
2021/05/26 MySQL