javascript当中的代码嗅探扩展原生对象和原型(prototype)
2013-01-11 00:00
836 查看
注:翻译之中有什么不恰当的地方,欢迎大家指正,祝大家双节快乐!
如果不是有特殊需要而去扩展原生对象和原型(prototype)的做法是不好的
除非这样做是值得的,例如,向一些旧的浏览器中添加一些ECMAScript5中的方法。
在这种情况下,我们一般这样做:
如果我们比较偏执,为了防止别人将map定义为其它意想不到的值,像true或其他,我们可以 将检测代码改为下面这样:
(尽管这将破坏其它开发者的map定义,并影响他们功能的实现)
但是,在一个充满敌意和残酷竞争的环境下(换句话说,但你提供或者使用一个js库时),你不应该相信任何人。如果其他人的js代码先于你的js代码加载,并且以某种方式定义了一个不完全兼容ES5的map()方法,导致你的代码不能正常运行,该怎么办呢?
不过,你可以相信浏览器,如果Webkit内核实现了map()方法,你可以放心,这个方法肯定会正常运行。否则的话,你就要用你的代码进行检测了。
幸运的是,这在JavaScript当中很容易实现,当你调用原生函数的toString方法的时候,会返回一个函数的字符串,该函数的函数体是[native code]。
例如在Chrome的控制台下:
一个适当的代码检查向来就是一个稍微令人不快的事,因为不同浏览器对空格和换行处理的太过轻率。测试如下:
只简单的去掉\s会得到更实用的字符串:
你可以将它封装成一个可以重用的shim()函数,这样以来你就没有必要去重复所有的类似!
Array.prototype...这样的操作了。这个函数会接受一个对象作为参数(例如,Array.prototype),一个将要添加的属性(例如 'map')和一个要添加的函数。
测试:
(完)^_^
如果不是有特殊需要而去扩展原生对象和原型(prototype)的做法是不好的
//不要这样做 Array.prototype.map = function() { // 一些代码 };
除非这样做是值得的,例如,向一些旧的浏览器中添加一些ECMAScript5中的方法。
在这种情况下,我们一般这样做:
if (!Array.prototype.map) { Array.prototype.map = function() { //一些代码 }; }
如果我们比较偏执,为了防止别人将map定义为其它意想不到的值,像true或其他,我们可以 将检测代码改为下面这样:
if (typeof Array.prototype.map !== "function") { Array.prototype.map = function() { // 一些代码 }; }
(尽管这将破坏其它开发者的map定义,并影响他们功能的实现)
但是,在一个充满敌意和残酷竞争的环境下(换句话说,但你提供或者使用一个js库时),你不应该相信任何人。如果其他人的js代码先于你的js代码加载,并且以某种方式定义了一个不完全兼容ES5的map()方法,导致你的代码不能正常运行,该怎么办呢?
不过,你可以相信浏览器,如果Webkit内核实现了map()方法,你可以放心,这个方法肯定会正常运行。否则的话,你就要用你的代码进行检测了。
幸运的是,这在JavaScript当中很容易实现,当你调用原生函数的toString方法的时候,会返回一个函数的字符串,该函数的函数体是[native code]。
例如在Chrome的控制台下:
> Array.prototype.map.toString(); "function map() { [native code] }"
一个适当的代码检查向来就是一个稍微令人不快的事,因为不同浏览器对空格和换行处理的太过轻率。测试如下:
Array.prototype.map.toString().replace(/\s/g, '*'); // "*function*map()*{*****[native*code]*}*" // IE // "function*map()*{*****[native*code]*}" // FF // "function*map()*{*[native*code]*}" // Chrome
只简单的去掉\s会得到更实用的字符串:
Array.prototype.map.toString().replace(/\s/g, ''); // "functionmap(){[nativecode]}"
你可以将它封装成一个可以重用的shim()函数,这样以来你就没有必要去重复所有的类似!
Array.prototype...这样的操作了。这个函数会接受一个对象作为参数(例如,Array.prototype),一个将要添加的属性(例如 'map')和一个要添加的函数。
function shim(o, prop, fn) { var nbody = "function" + prop + "(){[nativecode]}"; if (o.hasOwnProperty(prop) && o[prop].toString().replace(/\s/g, '') === nbody) { //表名是原生的! return true; } //新添加的 o[prop] = fn; }
测试:
//这是原生的方法 shim( Array.prototype, 'map', function(){/*...*/} ); // true //这是新添加的方法 shim( Array.prototype, 'mapzer', function(){alert(this)} ); [1,2,3].mapzer(); // alerts 1,2,3
(完)^_^
相关文章推荐
- javascript当中的代码嗅探扩展原生对象和原型(prototype)
- 扩展javascript原生对象
- 利用原型对原始对象的方法进行扩展(javascript面试题)
- 【Array类型】JavaScript中的原生对象以及Microsoft AJAX Library中的相关扩展
- 原生JavaScript中的原型概念(代码实例详解)
- JavaScript之面向对象学习五(JS原生引用类型Array、Object、String等等)的原型对象介绍
- javascript原型prototype代码片段笔记
- JavaScript中使用prototype来扩展对象,举例
- javascript原型对象prototype
- javascript 对象 与 prototype 原型
- 【Error类型】JavaScript中的原生对象以及Microsoft AJAX Library中的相关扩展
- JavaScript 的原型对象 Prototype
- JavaScript的constructor 、prototype解析 -- 原型模式知识扩展
- Javascript面向对象扩展库代码分享
- 利用prototype属性,对JavaScript对象进行功能扩展,比如数组对象Array,String等
- javascript中面向对象中对象,属性,原型链和一些扩展知识总结
- 【Function类型】JavaScript中的原生对象以及Microsoft AJAX Library中的相关扩展
- Javascript(二)-05-(常见对象-String-原型属性prototype)
- 本地对象Array的原型扩展实现代码
- JavaScript内置对象扩展原型函数收集贴