经过我多年的开发经验和牛逼的思维方式,终于可以来说说点号这王八犊子这些年到底都做了什么亏心的事 —扯淡新记。
作为一个半标准的前端码农,我深刻的意识到,JavaScript全程都在耍我们,就这个点号就能够让你一直懵逼,这种词法文法,和语法实在是让人嘴角莫名地一抽,说好的简单呢。
果然,入门确实简单,直接套Java
或者C
,C+
+的语法,然后改几个保留字,稍微瞄一下它的语法,OK!,入门啦,然而,只想说,你是入了门,但是只是前脚迈进了门,后脚还在门外面呢!
啊!莫大的悲哀啊!主要是近些年前端迸发,思想,语言,不断创新,完全跟不上脚步,只想说,大佬们麻烦你们停停脚吧!不累啊。
算了,还是回归主题,说点实在的。
我们学习JavaScript
,用于各种开发,但是很多人对于对象的点号使用呢,并没有去过多的思考,基本就是直接用了,这就是后脚还没有迈进门的,对象啊,访问函数啊,属性啊,用点号去处理,可是这个点号在JavaScript
编译器是怎么处理的呢,是不是有一丝好奇了,怎么处理的呢?
正所谓最好的学习方式就是探索,我们也来试试能不能玩出点号的花样!
我们先做如下几组测试,你可以先猜猜他们的答案是什么?
[
对了我这里写的中括号斜杠[\]
表示的斜杠后面的东西是可以重复无数次但至少有一个,比如[\空格]
表示空格可以重复无数次,但至少有一个
测试组
1.toString()
1.valueOf()
(1).toString()
(1).valueOf()
1..toString()
1..valueOf()
1[\空格].toString()
1[\空格].valueOf()
1[\tab].toString()
1[\tab].valueOf()
1[\空格].[\空格]toString()
1[\空格].[\空格]valueOf()
1[\tab].[\tab]toString()
1[\tab].[\tab]valueOf()
'abc'.toString()
'abc'.valueOf()
true.toString()
true.valueOf()
var obj = {t : 1, m : '123', q : {q : 2, m : '234', t : undefined}};
obj.t;
obj.q;
现在公布结果
1.toString()
1.valueOf()
//Uncaught SyntaxError: Invalid or unexpected token
//Uncaught SyntaxError: Invalid or unexpected token
(1).toString()
(1).valueOf()
//"1"
//1
1..toString()
1..valueOf()
//"1"
//1
1[\空格].toString()
1[\空格].valueOf()
//"1"
//1
1[\tab].toString()
1[\tab].valueOf()
//"1"
//1
1[\空格].[\空格]toString()
1[\空格].[\空格]valueOf()
//"1"
//1
1[\tab].[\tab]toString()
1[\tab].[\tab]valueOf()
//"1"
//1
'abc'.toString()
'abc'.valueOf()
//"abc"
//"abc"
true.toString()
true.valueOf()
//"true"
//true
var obj = {t : 1, m : '123', q : {q : 2, m : '234', t : undefined}};
obj.t
obj.q;
//1
//Object {q: 2, m: "234", t: undefined}
现在可能你会有一些疑惑,这里开始一一解答
基础来一波
首先我们要知道一些概念,是不是我们一直以来都只有对象可以进行点号属性访问,但是呢,在我们实验样例中,直接对原始值(直接量)[两个好像多可以说,原始值官方的]进行了属性访问,为什么可以这样呢。
因为JavaScript
编译器对于原始值使用点号属性访问会将他们临时转换为一个对象,比如说数字就变成Number
对象,字符串就变成了String
对象等等,然后就可以用对象的属性访问了。
当然null
和undefined
是不行的,因为他们没有封装的对象,准确一点来说,null
是一个最奇葩的东西,它本身就是一个对象,一个没有显性函数和属性的对象,并且不能赋值,而且他和Object
可以说是分开的,也就是说它不继承于Object
,它是一个独立的出来的对象,用来表示不存在对象,一个对象用来表示不存在的对象,本身就是一个矛盾,这个问题在JavaScript
已经存在已久,所以暂时不用纠结。
恩,上面对于原始值可以用点号来获取属性的原理讲了,现在来一一解释答案为什么是这样。
1.toString()
1.valueOf()
这个东西报错的原因呢,提示也基本给出来了,是一个非法的,不在预料之内的行为,因为当JavaScript
编译器检测到一个数字后面有点号时会默认为你是在写一个浮点数,那么很不幸就变成了(1.)toString()
,所以才报错了。
(1).toString()
(1).valueOf()
就我前面将的基础,答案自然如此,1
转换为Number
,然后调用Number
的toString
和valueOf
方法
1..toString()
1..valueOf()
这里就有点飞了,用了两个点号竟然正确了,好牛逼的东西,主要是因为当检测完第一个点号后,JavaScript
编译器就不会再认为碰到点号是浮点数了,而是调用属性或者方法,所以这里的实际情况就变成了这样(1.).toString()
,或者可以认为是这样(1.0).toString()
,当然并没有区别,JavaScript
将1.[\0]
当做是整数而不是浮点数
1[\空格].toString()
1[\空格].valueOf()
这里就飞起了,包括接下来的几个基本都是一样的原因,JavaScript
编译器在处理这个问题上会将空格自动忽略掉,当然不是直接去掉空格,不然不就又报错了吗?,只要是JavaScript
编译器处理的时候是一步一步来的,当检测到空格的时候,已经将1
这个数字处理完了,即便是检测到了点号也不会当成是浮点数,你见过浮点数中有空格的吗,显然没有。
1[\tab].toString()
1[\tab].valueOf()
上面同理
1[\空格].[\空格]toString()
1[\空格].[\空格]valueOf()
和上面同理
1[\tab].[\tab]toString()
1[\tab].[\tab]valueOf()
和上面同理
'abc'.toString()
'abc'.valueOf()
这里明白的是,字符串转化为String
对象后,他们的toString
和valueOf
的返回值是一样。我们这里要分清出一个概念,虽然toString
和valueOf
函数我们可以覆盖掉,但是他们都有自己本身的含义,toString
返回本对象类型的字符串的表达形式,而valueOf
则是返回这个对象所要表达的值。
true.toString()
true.valueOf()
同上了
var obj = {t : 1, m : '123', q : {q : 2, m : '234', t : undefined}};
obj.t;
obj.q;
这个东西就不用多说了,自己用吧。
总结
我们来总结一下点号的牛逼之处。针对原始值会临时转换为它对应的封装对象,然后呢就它使用注意的地方,对于数字啊。
然后特别值得注意的就是,即便是原始值转换为了封装的对象,但是这是临时的,点号用完之后就立马删除了,谨记。
[]
的用处和点号有点类似又有不同,下一篇可能会讲[]
中括号和点号的激情四射,所以还是尽情期待