本系列将会写一些在正常工作中会遇到的一些坑,然后分析它们的产生原因及解决办法.本文的内容主要来自<you don’t know JS>及日常工作的问题的一些总结.
关于arguments的使用:
arguments在ES6之前简直就是福音,因为在ES6之前是没有办法取到函数的参数组成的数组的.
但是arguments在使用的过程中还是有一些坑的,我们来看一下:
1 | function foo(a) { |
在向函数传递参数的时候,arguments数组中的对应单元会和命名参数建立关联,以得到相同的值,但是当函数在调用的时候没有传递参数时,因为没有参数,自然arguments就无法和函数建立关联了,自然就是undefined.
try/catch/finally的内容执行先后的问题
finally中的代码总是会在try之后执行,如果有catch的话会在catch之后执行.其实也可以把finally中的代码当做一个回调函数.无论出现什么情况,最后一定会被调用.
1 | function foo() { |
在这里return42先执行,并将foo()函数的返回值设置为42.try执行完毕后执行finally.console.log()显示的是函数的返回值.
对于这个问题还有一个很好玩的东西,就是当你在finally中进行抛出异常时,其实try中的返回值就不生效了.
1 | function foo() { |
其实综上而言,不论try中执行的是什么东西,即使是return
或者throw
等让函数立即结束的语句,最后finally也会成功执行.但是当finally
中抛出异常时,try
中的代码其实就相当于无效了.也就是finally中的值会最终覆盖掉try中的值.
关于全局的DOM变量
当我们在文档流中加入 <div id="foo"></div>
时,我们在其下面的js文档中能否找到foo这个变量呢?答案是可以!
1 | //我们直接在文档的下面进行类型判定 |
关于属性的屏蔽
当我们在原型链中为底层函数操作原型链中的属性进行算术运算时,属性被被底层函数给屏蔽掉.
1 | var anotherObject = { |
其实想到原理就很简单,因为当我们把myObject
中的a,也就是anotherObject
中的a调用之后,相应的myObject.a
会得到anotherObject
中的a的值,也就是2.但是当我们对myObject
执行其属性的自加操作之后,它的底层其实是这样的:
1 | myObject.__proto__.a = 2; |
关于concat()方法连接数组和push()方法连接数组的区别
首先我们看一个例子:
1 | var nums = [2, 3, 4, 5]; |
其实看了这个例子大家应该都懂了,首先,concat
的作用是链接两个数组,会将两个数组拼合成一个数组,并且不会改变之前的数组的值,而是返回一个新数组.
而push()
则直接改变了数组的值,而且是直接将push()
中传的参数直接接到了数组的后面,也就是当我们在push()
中传参数组时,最后会得到一个嵌套的数组.