扩展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 DOM 学习第三章 内容表格
Feb 19 Javascript
jQuery EasyUI API 中文文档 - Pagination分页
Sep 29 Javascript
jquery检测input checked 控件是否被选中的方法
Mar 26 Javascript
Angularjs的ng-repeat中去除重复数据的方法
Aug 05 Javascript
Bootstrap基本插件学习笔记之轮播幻灯片(23)
Dec 08 Javascript
基于bootstrap风格的弹框插件
Dec 28 Javascript
浅谈JavaScript find 方法不支持IE的问题
Sep 28 Javascript
node.js+express+mySQL+ejs+bootstrop实现网站登录注册功能
Jan 12 Javascript
vue.js打包之后可能会遇到的坑!
Jun 03 Javascript
mpvue性能优化实战技巧(小结)
Apr 17 Javascript
Vue引入Stylus知识点总结
Jan 16 Javascript
vue项目在webpack2实现移动端字体自适配功能
Jun 02 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
php生成文件
2007/01/15 PHP
Trying to clone an uncloneable object of class Imagic的解决方法
2012/01/11 PHP
php中选择什么接口(mysql、mysqli)访问mysql
2013/02/06 PHP
php发送post请求的三种方法
2014/02/11 PHP
smarty模板引擎基础知识入门
2015/03/30 PHP
解决laravel 5.1报错:No supported encrypter found的办法
2017/06/07 PHP
PHP实现redis限制单ip、单用户的访问次数功能示例
2018/06/16 PHP
php使用scandir()函数扫描指定目录下所有文件示例
2019/06/08 PHP
Laravel 框架返回状态拦截代码
2019/10/18 PHP
动态加载js、css等文件跨iframe实现
2014/02/24 Javascript
javascript入门教程基础篇
2015/11/16 Javascript
AngularJS表单提交实例详解
2017/02/18 Javascript
详解node-ccap模块生成captcha验证码
2017/07/01 Javascript
详解使用PM2管理nodejs进程
2017/10/24 NodeJs
如何让你的JS代码更好看易读
2017/12/01 Javascript
Vue用v-for给src属性赋值的方法
2018/03/03 Javascript
小程序兼容安卓和IOS数据处理问题及坑
2018/09/18 Javascript
Vue监听事件实现计数点击依次增加的方法
2018/09/26 Javascript
浅谈Angular7 项目开发总结
2018/12/19 Javascript
[01:43]3.19DOTA2发布会 三代刀塔人第三代
2014/03/25 DOTA
[02:33]2018 DOTA2亚洲邀请赛回顾视频 再次拾起那些美妙的时刻
2018/04/10 DOTA
python从ftp下载数据保存实例
2013/11/20 Python
在Linux上安装Python的Flask框架和创建第一个app实例的教程
2015/03/30 Python
利用Python进行数据可视化常见的9种方法!超实用!
2018/07/11 Python
python 列表推导式使用详解
2019/08/29 Python
浅谈Python访问MySQL的正确姿势
2020/01/07 Python
Python 格式化打印json数据方法(展开状态)
2020/02/27 Python
python 制作简单的音乐播放器
2020/11/25 Python
使用CSS实现阅读进度条
2017/02/27 HTML / CSS
CSS3实现伪类hover离开时平滑过渡效果示例
2017/08/10 HTML / CSS
办公室内勤工作职责
2013/12/11 职场文书
父亲追悼会答谢词
2014/01/17 职场文书
职业培训师职业生涯规划
2014/02/18 职场文书
创建文明城市标语
2014/06/16 职场文书
小区门卫的岗位职责
2014/09/26 职场文书
Mysql如何实现不存在则插入,存在则更新
2022/03/25 MySQL