总结了几个很有意思的基础题目,分享一下。
为什么 0.1 + 0.1 !== 0.2
看到这个问题,不得不想到计算机中的数据类型,其中浮点数表示有限的精度。那么它就无法精确的表示所有的十进制小数,所以在在某些情况下,浮点数的运算可能会导致微小的精度误差。这就是为什么 0.1 + 0.1
不等于 0.2
的原因。
具体来说,0.1
和 0.2
这两个数字都无法在二进制浮点数表示中精确地表示为有限位数的小数。这导致了一个微小的误差,当它们相加时,这个误差会叠加,使得结果不等于 0.2
。
这个问题不仅适用于 JavaScript,还适用于大多数编程语言中使用浮点数表示的情况。为了处理这种情况,通常需要在比较浮点数时使用某种容忍误差的方法,而不是直接进行相等性比较。
在 JavaScript 中,可以使用以下方法来处理浮点数的比较:
// 使用小数点后的位数来比较
const num1 = 0.1 + 0.1;
const num2 = 0.2;
const tolerance = 0.000001; // 定义一个容忍误差
if (Math.abs(num1 - num2) < tolerance) {
console.log("它们大致相等");
} else {
console.log("它们不相等");
}
[“1”,“2”,“3”].map(parseInt) 结果是什么
第一感觉是不是打印[“1”, “2”, “3”]。不认真看确实会有这样的结论。实际上并不是。
这个题目涉及到了map和parseIent两个知识点,首先了解一下这两个函数。
- map:JavaScript 中的
map()
函数是数组对象的一个高阶函数,它用于对数组的每个元素执行一个指定的函数,并返回一个新的数组,新数组中的元素是原始数组元素按照指定函数进行转换后的结果。map()
函数的基本语法如下:
array.map(callback(currentValue[, index[, array]])[, thisArg])
参数说明:
callback
:一个函数,用于对每个元素进行处理。这个函数接受三个参数:currentValue
:当前正在处理的数组元素。index
(可选):当前元素的索引。array
(可选):调用map()
的数组本身。
thisArg
(可选):可选参数,用于指定callback
函数中this
的值。
map()
函数的工作流程如下:
- 从数组的第一个元素开始,依次对每个元素执行
callback
函数。 - 将
callback
函数的返回值存储在一个新数组中。 - 返回新数组作为
map()
函数的结果。
- parseInt:函数接受两个参数:要解析的字符串和基数(进制)。但在
map
中,parseInt
被传递了三个参数:当前元素、当前索引和数组本身。
所以[“1”, “2”, “3”].map(parseInt)的结果是[1, NaN, NaN]。
map
将按照以下方式调用 parseInt
:
- 第一次调用:
parseInt("1", 0, ["1", "2", "3"])
,其中基数为 0(表示自动识别进制)。 - 第二次调用:
parseInt("2", 1, ["1", "2", "3"])
,其中基数为 1。 - 第三次调用:
parseInt("3", 2, ["1", "2", "3"])
,其中基数为 2。
parseInt
在解析字符串时,如果第一个字符无法转换为数字,则返回 NaN
。在这里,第一次调用 parseInt
时,字符串 “1” 可以成功解析为数字 1。然而,在第二次和第三次调用时,基数参数不符合期望的进制,因此解析失败,返回 NaN
。
因此,["1", "2", "3"].map(parseInt)
的结果是 [1, NaN, NaN]
,这是由于 parseInt
函数在不同基数下的解析失败导致的。
下列题目输出结果
(function a () {
"use strict";
var a = b = 3;
})();
console.log("输出a" + (typeof a !== 'undefined'));
console.log("输出b" + (typeof b !== 'undefined'));
非严格模式下运行
代码块 (function a (){ var a = b =3; })();
包含了一个函数表达式。在这个代码块中,有以下操作:
-
var a = b = 3;
:这个语句声明了变量a
,但同时也声明了一个全局变量b
并将其赋值为3
。在非严格模式下,未使用var
、let
或const
声明的变量会成为全局变量。 -
console.log("输出a" + (typeof a !== 'undefined'))
:在这里,你尝试检查变量a
是否被定义。由于a
被声明为局部变量,因此在函数外部不可见,typeof a
返回"undefined"
,因此整个表达式的结果是"输出afalse"
。 -
console.log("输出b" + (typeof b !== 'undefined'))
:这里尝试检查变量b
是否被定义。虽然b
在函数内部赋值,但由于没有使用var
、let
或const
来声明它,它成为了一个全局变量,因此在整个页面的作用域内都可见。typeof b
返回"number"
(因为它被赋值为3
),因此整个表达式的结果是"输出btrue"
。
根据非严格模式下的变量作用域和声明方式,代码的输出结果是"输出afalse"
和"输出btrue"
。
严格模式下
严格模式下不会输出任何结果,而会抛出错误。
在上面代码块内,有一个立即执行函数 (function a (){ ... })();
,它包含了以下行为:
-
var a = b = 3;
:在这行代码中,尝试声明一个局部变量a
,并将其赋值为b
。然而,这里存在一个陷阱。由于没有使用var
、let
或const
来声明b
,它成为了一个全局变量,而不是局部变量。这意味着b
的作用域会泄漏到外部的函数作用域(全局作用域),而不是被限制在函数内部。 -
在严格模式下,
var a
的作用域仅限于函数内部,所以a
只能在函数内部访问,而在函数外部是不可见的。因此,尝试在函数外部访问a
时会导致Uncaught ReferenceError
错误。 -
同样,在严格模式下,尝试在函数外部访问全局变量
b
时,也会导致Uncaught ReferenceError
错误,因为全局变量b
在非严格模式下会被隐式地创建,但在严格模式下需要显式声明。
所以在定义**var a = b =3;**时就会抛出错误,不会执行打印的语句