41条对违反抽象原则行为的讨论之后,下面聊一聊终极违例。由于对象共享原型,因此每一个对象都可以增加、删除或修改原型的属性。这个有争议的实践通常称为猴子补丁。

猴子补丁示例

猴子补丁的吸引力在于其强大。数组缺少一个有用的方法吗?你自己就可以增加它。

Array.prototype.split=function(i){
return [this.slice(0,i),this.slice(i)];
}

很完美,现在可以在任意的数组上调用这个方法了。但当多个库以不兼容的方式给同一个原型打猴子补丁时,另外的库使用同一个方法名给Array.prototype打猴子补丁。

Array.prototype.split=function(){
var i=Math.floor(this.length);
return [this.slice(0,i),this.slice(i)];
}

问题

现在,任一对数组split方法的使用都大约有50%的机会被破坏,这取决于它们期望这两个方法哪一个被调用。
至少,任一修改其享原型的程序库都应当清晰地记录其修改。这至少能给使用者在关于不同库之间潜在的冲突提供足够的警告。但是,两个以冲突的方式给原型打猴子补丁的程序库不能在同一个程序中使用。

替代的方法

一种替代的方法是,如果库仅仅是将给原型打猴子补丁作为一种便利,那么可以将这些修改置于一个函数中,用户可以选择调用或忽略。

function addArrayMethods(){
Array.prototype.split=funciton(i){
return [this.slice(0,i),this.slice(i)]
}
}

这种方法只有在程序库提供了addArrayMethods函数时才能工作,而实际上并不依赖于Array.prototype.split函数。

ployfill

尽管猴子补丁很危险,但有一种告别可靠而且有价值的使用场景:ployfill。js程序和库经常部署在多个平台,这些平台实现了多少个标准API可能是有区别的。缺失的方法的行为是广泛支持的标准所定义的,而且许多程序和库可能依赖这些方法。由于它们的行为是标准化的,因此实现这些方法并不会造成与库之间不兼容性的类似的风险。事实上,多个库都可以给同一个标准方法提供实现(假设是被正确实现),因为它们都实现了相同的标准API。
你可以通过使用带有测试条件的守护猴子补丁来安全地弥补这些平台的差距。

if(typeof Array.prototype.map!=="function"){
Array.prototype.map=function(f,thisArg){
var res=[];
for(var i=0,n=this.length;i < n;i++){
res[i]=f.call(thisArg,this[i],i);
}
return res;
}
}

提示

  • 避免使用轻率的猴子补丁

  • 记录程序库所执行的所有猴子补丁

  • 考虑通过将修改置于一个导出函数中,使猴子补丁成为可选的

  • 使用猴子补丁为缺失的标准API提供polyfills

[Effective JavaScript 笔记]第42条:避免使用轻率的猴子补丁的更多相关文章

  1. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  2. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  3. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  4. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  5. [Effective JavaScript 笔记]第50条:迭代方法优于循环

    "懒"程序员才是好程序员.复制和粘贴样板代码,一但代码有错误,或代码功能修改,那么程序在修改的时候,程序员需要找到所有相同功能的代码一处处进行修改.这会使人重复发明轮子,而且在别人 ...

  6. [Effective JavaScript 笔记]第68条:使用promise模式清洁异步逻辑

    构建异步API的一种流行的替代方式是使用promise(有时也被称为deferred或future)模式.已经在本章讨论过的异步API使用回调函数作为参数. downloadAsync('file.t ...

  7. [Effective JavaScript 笔记]第64条:对异步循环使用递归

    假设需要有这样一个函数,接收一个URL的数组并尝试依次下载每个文件直到有一个文件被成功下载.如果API是同步的,使用循环很简单实现. function downloadOneSync(urls){ f ...

  8. [Effective JavaScript 笔记]第46条:使用数组而不要使用字典来存储有序集合

    对象属性无序性 js对象是一个无序属性集合. var obj={}; obj.a=10; obj.b=30; 属性a和属性b并没有谁前谁后之说.for...in循环,先输出哪个属性都有可能.获取和设置 ...

  9. [Effective JavaScript 笔记]第45条:使用hasOwnProperty方法以避免原型污染

    之前的43条,44条讨论了属性的枚举,但都没有彻底地解决属性查找中原型污染的问题.看下面关于字典的一些操作 'zhangsan' in dict; dict.zhangsan; dict.zhangs ...

随机推荐

  1. Javascript基础系列之(八)Javascript的调试与优化

    Javascript的错误主要是语法错误和运行时的错误,前者在代码解析时就会出错,影响程序的运行.后者称为异常,影响它所运行的线程.下面就Javascript常见错误进行分析 1.常见的错误和异常 i ...

  2. 小结-Splay

    参照陈竞潇学长的模板写的BZOJ 3188: #include<cstdio> #include<cstring> #include<algorithm> #def ...

  3. ES6的模块、构建工具及应用的发布

    作者:寸志链接:https://zhuanlan.zhihu.com/p/19569085来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 总的说来就是按照将来的标准书写 ...

  4. 【CodeForces 625A】Guest From the Past

    题 题意 一升奶可以花费a元,也可以话b元买然后获得c元,一开始有n元,求最多买多少升奶. 分析 贪心,如果b-c<a,且n≥b,那就买b元的,n先减去b再看看够买多少瓶,然后再+1瓶,余款再购 ...

  5. TYVJ P2002 扑克牌

    背景 Admin生日那天,Rainbow来找Admin玩扑克牌……玩着玩着Rainbow觉得太没意思了,于是决定给Admin一个考验~~~ 描述 Rainbow把一副扑克牌(54张)随机洗开,倒扣着放 ...

  6. OPENSSL编程入门学习

    相关学习资料 http://bbs.pediy.com/showthread.php?t=92649 https://www.openssl.org https://www.google.com.hk ...

  7. 多线程练习(java)

    public class TestThread { public static void main(String[] args) { RandomNumber r=new RandomNumber() ...

  8. frameset用法

    <html> <frameset rows="15%,*" border="1" frameborder="1" scro ...

  9. apt-get常用命令

    apt-get常用命令 一,什么的是apt-get 高级包装工具(英语:Advanced Packaging Tools,简称:APT)是Debian及其衍生发行版(如:ubuntu)的软件包管理器. ...

  10. TFS 配置 报表权限问题

    通过[项目门户网站]访问,却被提示ReportService权限不足时, 提示:处理报表时出错. (rsProcessingAborted)  对数据集 “dsiteration” 执行查询失败 同样 ...