JavaScript 这门语言,让开发者感受编程乐趣的方式多种多样。今天掌握了一个新技能。我们来看下:
data.key = value
var a = data.key
value === a
这段代码平淡无奇对吗?但是,如果我告诉你,最后返回的结果是 false,是不是很好玩。
很显然,在这段代码前面,我还干了一些其他事情,导致最后的比较返回 false。我们来看看我都做了什么:
Object.defineProperty(data, 'key', {
get() {
return this._originalData.key
},
set(v) {
this._originalData.key = { ...v }
},
})
当前,在这之前,我还处理 _originalData 等,但这一段代码就可以了。也就是说,我规定了 key 属性在被赋值的时候,都要做怎么样的处理。这是已经到元编程的层面了,所以说 js 好玩。
这不单单是好玩的问题,而是在实际编程中,我们可能遇到的问题。你可能会问,谁会在自己的项目中搞这种蛋疼的事?不过很抱歉,很多处理数据的库,都会这么干,用来解决一些特别的逻辑。我想有一天你肯定也会这么干。我们来看一个可能出现 bug 的实用场景。
const files = []
const file = input()
files.push(file)
if (files.find(item => item === file) {
// do something
}
类似的代码我们经常用吧。把一个元素加入到一个数组中,需要的时候,又在数组中,去找这个元素。这么干,说实话,经常出事。所以,我建议你最好 files.find(item => item.id === file.id),用一个字符串或数字作为唯一标志。不然翻车别怪我没提醒过。
为什么会这样呢?
你怎么知道 push 没有被修改过?
files.push = function(v) {
return Array.prototype.push.call(this, { ...v })
}
所以,你敢随便自认为吗?js 编程就是这么任性。甚至有些人直接在原型链顶端搞事情,你扛得住吗?不要用一个没看过源码的不可靠第三方库!!!这是老人言。现在有些人,非蠢即坏,你防不住的。另外,善用 Reflect 或许也是忠告。
虽然你可以
const pushed = files.push(file)
这样可以得到 push 之后的真实数据,然而,然而,你怎么知道在类似 angular 之类的框架中,这些数据有没有被篡改过。总之,少年,我劝你善良。
原文出自:www.tangshuang.net