数组排序问题
|
|
sort()
默认情况下会按照Unicode码点排序,而不是数值顺序排序,所以正确的解决方案为:
|
|
0.1+0.2 !== 0.3的问题
先看如下代码
|
|
本质上这是二进制浮点数造成的精度丢失问题,这种问题也存在于除JavaScript之外的其他语言中,可以参考0.30000000000000004.com
因为计算机只能读懂二进制数值,我们看下0.1和0.2转换成二进制:
0.1 => 0.0001 1001 1001 1001…(无限循环)
0.2 => 0.0011 0011 0011 0011…(无限循环)
双精度浮点数的小数部分最多支持 52 位,所以计算后会进行小数位的限制截断,也就造成了舍入误差,再次转换成十进制后就是我们所看到的0.30000000000000004
解决方法
|
|
toFixed()
方法是保留小数后面的位数是几位,注意:得到的结果是字符串
全局变量问题
|
|
一般会有不少人觉得应该打印0,因为b=3是函数内声明,属于局部变量。
这里var a=b=3
是个坑,赋值运算是从右往左的,所以这里的b=3是全局变量。
所以声明变量建议单个单个的来。
变量提升问题
|
|
因为预解析的原因,所以var d
的代码会提升到代码顶部,且值为undefined,然后执行流程语句,因为d为undefined,转为布尔值为false,所以不会进入if判断语句,所以打印结果为undefined
下面的代码也是同理
|
|
匿名函数预解析1
|
|
匿名函数的预解析会把函数提升到函数所在作用域的顶部,声明先于调用,而第二个foo函数会覆盖第一个foo函数的声明,所以两次foo()
的调用都是在执行第二个声明的函数,所以打印两次2
匿名函数预解析2
|
|
匿名函数会预解析,但是函数表达式不会预解析。
所以匿名函数getName会提升到所在作用域顶部,然后依次执行代码,执行到函数表达式时,getName函数表达式会覆盖匿名函数getName,所以打印结果是2
匿名函数预解析3
|
|
匿名函数fn1会提前预解析,提升到作用域顶部。 a变量也会提升到代码顶部并初始化值为undefined。
执行fn2。调用fn1是执行fn1函数,而fn1执行时a只和fn1所在作用域有关,调用时a只是初始化,还未赋值为333,所以打印结果为undefined
null和undefined
|
|
请记住这个特殊情况吧!
所以我建议写代码判断相等用===
还有null和undefined的区别
null表示”没有对象”,即该处不应该有值。
undefined表示”缺少值”,就是此处应该有一个值,但是还没有定义。
Math.min>Math.max()
|
|
typeof(null)===’object’
|
|
这是错的,虽然他返回的结果是true,但这是JavaScript设计的错误,考虑到后兼容,就保持了这一错误
JavaScript注释
|
|
上面的代码之后x和y的值是多少?
答案是5和1.
因为<!--
会把后面的代码注释掉(虽然是HTML注释,但这里浏览器依然会当做注释),所以后面的代码都是不影响y的值的,就像下面代码
|
|
哪怕是浏览器不能识别,会报错的字符依然不受影响,因为浏览器会跳过注释执行代码
JavaScript函数中参数的传递
|
|
这道代码题最开始我疑惑了挺久,在网上也有搜过,貌似对于值传递一直有争议,我自己刚开始也不是很明白。
先看下答案:
|
|
现在我理解了所谓的函数参数都是值传递的说法。
首先,函数调用的时候,其中的参数是实参把值复制给形参的一个过程。
如果实参是原始类型,参数传递则是值的直接复制;如果实参是引用类型,参数传递则是引用类型的地址的传递(指针的传递),相当于实参和形参都同时指向这个引用类型的内存。
再看题目中,重点就在于fn函数中,a和b都是局部变量,
执行的第一行是把a的属性改变了,其中a指向的和变量young一样的内存:{name: 'su'}
,改变a的属性就是改变内存中的属性,所以会反映到他的指针上面,也就是变量young也会改变,所以打印的young值也确实改变了;
执行的第二行中,本来形参b的指针指向和old一样的:{age: 66}
,然后 b = {age: 20}
的赋值语句把b的指针改变了,指向了{age: 20}
,b不在指向{age: 66}
了,但是old还依然指向{age: 66}
,所以实参old对应的内存并没有改变,所以会打印{age: 66}