具体代码实践中,我们会遇到如何重用或者嵌入自己的代码到已写好的函数,比如前面的文章js深度拷贝所说的JSON.stringify来实现deepClone出现的问题,为了避免循环引用,使用的时候需要用到的第二个参数,如何更优雅的实现呢?如下代码:
const stringify = JSON.stringify
// 重写stringify
JSON.stringify = function(...args) {
if (!args[1]) {
const cache = []
args[1] = (key, value) => {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
return // 或者 return undefined
}
cache.push(value)
}
return value;
}
}
return stringify.apply(this, args)
}
再举一个一般程序员会忽略的例子:例如new Date('2018-10-23 10:00:00')
这行代码大部分人都会认为ok,实际上在safari上就会是Invalid Date
,
简单的修改实现就是改成new Date('2018-10-23 10:00:00'.replace(/-/g, '/'))
,如下图:
-
非/
(数据库数据,国人习惯)。这个时候就可以用这种侵入式(重点,也是它的弊端)很强的方式统一修改了,如下:
const _Date = Date
Date = function(...args) {
// new 出来的
if (this instanceof Date) {
if (args.length === 1 && typeof args[0] === 'string' && args[0].length > 10) {
args[0] = args[0].replace(/-/g, '/')
}
return new _Date(args)
}
return _Date(args)
}
Date.prototype = _Date.prototype
Date.parse = function(...args) {
if (args.length === 1 && typeof args[0] === 'string' && args[0].length > 8) {
args[0] = args.replace(/-/g, '/')
}
return _Date.parse.apply(args)
}
// 代理实现不可枚举的key
Object.defineProperties(Date, Object.getOwnPropertyNames(_Date).filter(p => p!== 'prototype').reduce((c, p) => {
c[p] = {
enumerable: false,
get () {
return _Date[p]
}
}
return c
}, {}))
测试结果如下图;
重点、重点、重点
一定要克制,函数拦截侵入太强,使用不当或者过度使用,会导致问题很难追踪,另外代码阅读体验很差!!!