充满怪癖的Javascript变量声明

标签: javascript ;


我其实没有正经学过javascript,但是写网页又一定会遇到。之前用vue做了一个个人项目,基本上是现学现用,掉了很多次坑。现在有点时间,回过头来看看javascript的完整语法,只看了个开头,就给整不会了。那么多种变量声明的方式,到底有什么不同?

  • 像Python那样,不使用任何关键字,直接给一个变量赋初值,会隐式地制造一个全局变量,哪怕是在函数内部,它也是全局变量!这绝对是一个设计错误!

  • var声明的变量,也有很多怪癖:

    1. 如果在函数内部声明,变量的作用域就是整个函数——哪怕在块内部声明,它也是函数级变量;

    2. 如果在顶层声明var变量,它就是全局变量,同时,也会成为全局对象window的一个属性。我实在搞不懂正经人为什么会产生如此不正经的需求。

    3. var声明的变量可以在声明之前先引用,原因在于,javascript编译器会隐式地将该变量的声明(注:仅仅是声明,不包括赋初值!)移到块的头部。这是向Pascal致敬?

    4. 可以用var重复地声明同一个变量,javascript会自动删除冗余的声明。毫无疑问,这也是一个设计错误。除了隐藏BUG,我想不出来还有什么用?

    基于以上原因,正经人应该严格杜绝使用var来声明变量。总之,就当它不存在算了。至于不加任何关键字的变量声明,同样应该小心避免。特别是写惯了Python的时候,一不小心就犯错。

  • let的行为和其它正经语言的词法变量一样,在顶级声明,它就是全局变量,在函数内声明,它的作用域就是整个函数,在块内部声明,它的作用域就是块内部。同时,它不能重复声明,也不能在声明之前引用。这才是符合直觉的行为嘛。

  • const: 从字面意义出发,const应该声明一个不可变的对象,但其实不是。当const声明的对象指向一个值时,它的表现是常量,不接受修改。但当它声明的引用指向一个对象时,该对象其实是可变的。这让const这个声明变得毫无意义。如果有这种需求,为什么不直接用let来声明该对象呢?在现有的代码中,经常是const满天飞,大部分时候其实是用于定义函数。

const fn = (args) => { ... }

尽管这么做的人有自己的理由,但我认为,这些做法终究背离了它自身的语义。当然,这只是个人口味问题。

总之,我相信Javascript确实拥有一个优雅的内核,但是要正确地使用它,却必须先搞懂并记住它丑陋的一面,以免不小心使用到那些怪癖。