[Effective JavaScript 笔记]第42条:避免使用轻率的猴子补丁
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条:避免使用轻率的猴子补丁的更多相关文章
- [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法
js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...
- [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象
js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...
- [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符
“1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...
- [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码
函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...
- [Effective JavaScript 笔记]第50条:迭代方法优于循环
"懒"程序员才是好程序员.复制和粘贴样板代码,一但代码有错误,或代码功能修改,那么程序在修改的时候,程序员需要找到所有相同功能的代码一处处进行修改.这会使人重复发明轮子,而且在别人 ...
- [Effective JavaScript 笔记]第68条:使用promise模式清洁异步逻辑
构建异步API的一种流行的替代方式是使用promise(有时也被称为deferred或future)模式.已经在本章讨论过的异步API使用回调函数作为参数. downloadAsync('file.t ...
- [Effective JavaScript 笔记]第64条:对异步循环使用递归
假设需要有这样一个函数,接收一个URL的数组并尝试依次下载每个文件直到有一个文件被成功下载.如果API是同步的,使用循环很简单实现. function downloadOneSync(urls){ f ...
- [Effective JavaScript 笔记]第46条:使用数组而不要使用字典来存储有序集合
对象属性无序性 js对象是一个无序属性集合. var obj={}; obj.a=10; obj.b=30; 属性a和属性b并没有谁前谁后之说.for...in循环,先输出哪个属性都有可能.获取和设置 ...
- [Effective JavaScript 笔记]第45条:使用hasOwnProperty方法以避免原型污染
之前的43条,44条讨论了属性的枚举,但都没有彻底地解决属性查找中原型污染的问题.看下面关于字典的一些操作 'zhangsan' in dict; dict.zhangsan; dict.zhangs ...
随机推荐
- #Linux学习笔记# Linux文件的属性以及权限说明
1. Linux文件的属性 关于Linux文件的属性的说明和设置请参考鸟哥Linux私房菜:Linux 的文件权限与目录配置 2. 目录和文件的权限意义 在Linux系统中,每个文件都有三种身份的权限 ...
- 4G时代的抢钱之道
最近最大的事件恐怕就是移动的4G上线了,50元600M起计价,上网速度最高理论到达100Mbps,相当于一秒下载10MB的数据,或者是一分钟下载一张VCD(600M)电影. 当然,对于这样的流量套餐, ...
- tmux列表重命名
查看tmux会话列表时,会话名称是数值递增,不易识别 tmux ls 1: 1 windows (created Fri Oct 21 16:29:46 2016) [175x41]2: 1 wind ...
- document.cookie打不出来cookies
比如session这种设置,都是设置了HttpOnly 导致document.cookie看不到,这和xss 跨站脚本攻击(Cross Site Scripting)
- $().each() 与 $.each()解析
在jquery 中我们可以选择$().each() 与 $.each() 进行迭代对象和数组 $(items).each(function(){ //item }) , 而后者则 $.each(ite ...
- 配置域从DNS服务器以及缓存DNS服务器
一.域从DNS服务器的作用 我们在之前上一篇随笔里有提到,DNS服务器一般有三种类型,一个是Primary DNS Server(主DNS服务器),一个是Secondary DNS Server(从D ...
- 详解在visual studio中使用git版本系统(图文)
很多人已经在使用git(或正在转移到git上),在github.com上,也看到园子里不少同学的开源项目,非常不错.但相关教程似乎不多,所以趁着我自己的开源项目源码托管(https://github. ...
- 5.9-4用字符串生成器给字符串str追加1~10这10个数字
package zfc; public class ZfcShcq { public static void main(String[] args) { // TODO Auto-generated ...
- hdu1873优先队列
#include<stdio.h> #include<queue> using namespace std; struct node { int id; int val; fr ...
- SQL Server 2008 R2导出数据脚本的方法
以前看到有些朋友说必须SQL Server 2008才能导出包含数据的脚本,后来仔细研究发现其实SQL Server 2008 R2也是可以的,只需在导出的时候在高级中设置一下即可. 1.首先在数据库 ...