JavaScript世界中的强制性-侦探故事
内森,您不知道发现了什么。
我已经对此进行了数周的调查。一切始于去年十月的一个暴风雨之夜。我无意间偶然发现了Number
该类-我的意思是,为什么世界上JavaScript都有一个Number
类?
我没有为接下来要查找的内容做准备。
事实证明,JavaScript一直在不告诉您的情况下,将您的数字更改为对象,而您的对象更改为您的鼻子下面的数字。
JavaScript希望没有人能追上,但是人们一直在报告奇怪的意外行为,现在感谢您和您的问题,我有证据表明我需要对此事大肆宣扬。
到目前为止,这是我们发现的。我不知道我是否该告诉您-您可能要关闭JavaScript。
> function dis() { return this }
undefined
创建该函数时,您可能不知道接下来会发生什么。一切看起来都很好,一切都很好-现在。
没有错误消息,只是控制台输出中的单词“ undefined”,恰恰是您所期望的。毕竟,这是一个函数声明-不应返回任何内容。
但这仅仅是开始。接下来发生了什么,没人能预料到。
> five = dis.call(5)
Number {[[PrimitiveValue]]: 5}
是的,我知道,您期望得到一个5
,但是那不是您得到的,是-您得到了其他东西-有所不同。
这样的事情我也经历过。
我不知道该怎么做。它使我发疯。我无法入睡,无法进食,试图将其喝掉,但是没有多少山露会让我忘记。只是没有任何意义!
那是我发现真正发生的事情的时候-那是强制,它就在我眼前发生,但是我实在是太盲目看不到了。
Mozilla试图通过将其放置在他们知道没人看的地方来隐藏它-他们的文档。
经过数小时的递归阅读,重新阅读和重新阅读,我发现了这一点:
“ ...,原始值将转换为对象。”
就在这里,很明显,可以用Open Sans字体拼写出来。这就是call()
功能-我怎么会这么傻?
我的电话号码不再是一个电话号码。当我将它传递进去的那一刻call()
,它变成了别的东西。它变成了...一个对象。
起初我不敢相信。这怎么可能是真的?但是我不能忽略围绕我的证据。只要看一下就在这里:
> five.wtf = 'potato'
"potato"
> five.wtf
"potato"
wtf
是正确的。数字不能具有自定义属性-我们都知道这一点!这是他们在学院里教您的第一件事。
我们应该在看到控制台输出的那一刻就知道了-这不是我们认为的数字。这是一个冒名顶替者-一个物体冒充我们甜蜜的无辜数字。
这是... new Number(5)
。
当然!这是完全合理的。call()
有一件工作要做,他必须调用一个函数,然后要做他需要填充的事情this
,他知道自己不能用数字来做到这一点-他需要一个对象,并且他愿意做任何事情来获得它,甚至如果那意味着强迫我们的电话号码。当call()
看到数字时5
,他看到了机会。
这是一个完美的计划:等到没人看时,再用我们的电话换一个看起来像它的物体。我们得到一个数字,该函数被调用,没有人会更明智。
这确实是一个完美的计划,但是像所有计划一样,甚至是完美的计划,在其中也有一个漏洞,我们即将陷入其中。
瞧,call()
不明白的是,他不是镇上唯一可以强迫数字的人。毕竟这是JavaScript-到处都是强制。
call()
拿走了我的电话号码,直到我将面具从他的小骗子身上拉下并将他暴露给整个Stack Overflow社区,我才停下来。
但是如何?我需要一个计划。当然,它看起来像一个数字,但我知道不是,必须要有一种方法来证明这一点。而已!它看起来像一个数字,但是它可以像一个数字一样起作用吗?
我告诉five
我需要他变得大5倍-他没有问为什么,我也没有解释。然后,我做了任何优秀的程序员都会做的事情:我成倍增加。当然,他没有办法伪造自己的出路。
> five * 5
25
> five.wtf
'potato'
该死的!不仅five
乘法wtf
还不错。该死的家伙和他的土豆。
到底是怎么回事?我整个事情都错了吗?是five
真的多少?不,我必须丢失一些东西,我知道,有些东西我必须忘记,这些东西非常简单和基本,以至于我完全忽略了它。
这看起来不太好,我已经写了好几个小时的答案,但我离提出观点还差得远。我无法坚持下去,最终人们会停止阅读,我不得不思考一些事情,并且必须快速思考。
等一下!five
不是25,结果是25,25是一个完全不同的数字。当然,我怎么会忘记?数字是不可变的。当乘以5 * 5
任何东西时,您将只创建一个新数字25
。
那一定是这里发生的事情。我以某种方式乘法时five * 5
,five
必须将其强制为一个数字,并且该数字必须是用于乘法的数字。是乘积的结果被打印到控制台,而不是其five
本身的值。five
永远不会被分配任何东西-因此,它当然不会改变。
因此,我该如何five
为自己分配操作结果。我知道了。之前five
甚至有一个思考的机会,我大喊:“++”。
> five++
5
啊哈!我有他!大家都知道5 + 1
是6
,这是我需要公开的证据five
是不是一个数字!那是骗子!一个糟糕的冒名顶替者,不知道如何计算。我可以证明这一点。这是实数的作用方式:
> num = 5
5
> num++
5
等待?这是怎么回事 叹息,我陷入了破产的困境,five
以至于我忘记了邮政接线员的工作方式。当我++
在末尾使用时,five
是说要返回当前值,然后递增five
。将操作发生之前的值打印到控制台。num
实际上6
,我可以证明这一点:
>num
6
是时候看看five
真正的含义了:
>five
6
...这正是应该的。five
很好-但是我更好。如果five
仍然是一个对象,那意味着它仍然会拥有该属性,wtf
而我愿意打赌它没有的一切。
> five.wtf
undefined
啊哈!我是对的。我有他!five
现在是一个数字-它不再是一个对象。我知道这次乘法将无法保存。看five++
是真的five = five + 1
。与乘法不同,运算++
符为分配一个值five
。更具体地,分配给它的结果five + 1
,其就像在乘法返回一个新的不可变的情况下数。
我知道我有他,只是为了确保他不会从他那儿弯腰。我又袖手旁观了。如果我是对的,并且five
现在确实是一个数字,那么这将不起作用:
> five.wtf = 'potato?'
'potato?'
这次他不会骗我。我知道potato?
将要打印到控制台,因为那是作业的输出。真正的问题是,还会wtf
存在吗?
> five.wtf
undefined
就像我怀疑的那样-什么都没有-因为数字无法分配属性。我们是在学院第一年学到的;)
谢谢内森。多亏您提出这个问题的勇气,我终于可以把所有这些都抛在脑后,然后再提出一个新的案例。
像这样关于功能toValue()
。哦,亲爱的上帝。不!
++
似乎会影响基础类型