共计 3796 个字符,预计需要花费 10 分钟才能阅读完成。
1. 基本概念
1.1 数据类型
(1)typeof 操作符
console.log(typeof null); //“object”
用 typeof 操作符去监测 null,得到的类型是 object。
原因是 null 被认为是一个空的对象引用。
function func(){// do something}
console.log(typeof func); // "function"
function 虽然不是 6 大数据类型中的一种,但却可以被 typeof 操作符监测出来。
原因是函数在 ECMAScript 中是对象,但函数确实有一些特殊的属性,所以需要用 typeof 来区分。
(2)Undefined
var message;
console.log(message); // undefined
console.log(answer); // 报错
console.log(typeof message); // undefined
console.log(typeof answer); // undefined
声明后未初始化的变量默认值为 undefined,想获得一个未声明的变量会报错,这很好理解。
但是用 typeof 操作符监测声明后未初始化的变量和一个未声明的变量都会得到 undefined。虽然这两种变量从技术角度看有本质区别,但实际上也不可能对它们做任何操作。
所以在声明变量的时候显式地初始化是一个好的选择,这样监测出 undefined 就知道是未声明的变量了。
(3)Null
null 表示的是一个空对象指针,所以如果一个变量在之后准备保存对象,那么初始化的值为 null 是最合理的。这样只要检查 null 值就知道是否已经保存了一个对象的引用了。
console.log(undefined == null); // true
用相等操作符 (=) 去比较 undefined 和 null 会得到 true 的结果。
原因是 undefined 实际上是派生自 null。[这句话我觉得不用理解, 语言就是这么设计的。]
(4)Boolean
ECMAScript 中所有的值都有与 2 个 boolean 值对应的值:
数据类型 | 转换为 true | 转换为 false |
---|---|---|
Boolean | true | false |
String | 任何非空字符 | 空字符 |
Number | 任何非零数字值 | 0 和 NaN |
Object | 任何对象 | null |
Undefined | n/a(不适用) | undefined |
(5)Number
var floatNum1 = 1.; // 解析为 1
var floatNum2 = 10.0; // 解析为 10
由于保存浮点数值需要的内存空间是保存整数值的两倍,因此 ECMAScript 会不失时机地将浮点数值转换为整数值。
如果小数点后面没有跟任何数字,那么这个数值就可以作为整数值来保存。
console.log(0.1 + 0.2); // 0.30000000000000004
浮点数计算不精确。
基于 IEEE754 数值浮点计算产生误差,原因是计算机会先把 0.1 和 0.2 转化为二进制,再把相加的结果转化为十进制。在两次转化中产生了误差。
由于内存的限制,ECMAScript 并不能保存世界上所有的数值。最小数值为 5e-324,保存在 Number.MIN_VALUE 中;最大数值为 1.7976931348623157e+308,保存在 Number.MAX_VALUE 中。如果某次计算的结果得到了一个超出 JavaScript 数值范围的值,那么这个数值将被自动转换成特殊的 infinity 具体来说,如果这个数值是负数,则会被转换成 -infinity(负无穷),如果这个数值是正数,则会被转换成 Infinity(正无穷)。
可使用 isFinite()函数来确定一个数值是不是又穷的。
console.log(NaN == NaN); // false
NaN,即非数值(Not a Number)是一个特殊的数值,这个数值用于表示一个本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误了)。
NaN 本身有两个非同寻常的特点:
首先,任何涉及 NaN 的操作(例如 NaN/10)都会返冋 NaN, 这个特点在多步计算中有可能导致问题。
其次,NaN 与任何值都不相等,包括 NaN 本身。
这里我们探讨一个问题就是任何数据除以 0 只会返回 2 种结果:1 个是 NaN,一个是 Infinity。
下面看几个例子:
console.log(0/0); // NaN
console.log(true/0); // Infinity
console.log(false/0); // NaN
console.log("2222"/0); // Infinity
console.log(-1/0); // -Inifinity
console.log(undefined/0); // NaN
console.log(null/0); // NaN
从这几个例子中可以归纳出几个结论:
- 0/ 0 和 NaN/0 会得到 NaN (例子中 false 会转化为 0,undefined 会转化成 NaN,null 会转化为 0, 对象会转化为 NaN[示例中未举出])
- 其他任何转化为数字不为 0 的值除以 0 都会得到 Infinity (正值就是 Infinity,负值则为 -Infinity)
可用 isNaN()函数来判断这个参数是否“不是数值”。如果这个值不能被转化成数值,则返回 true。
console.log(isNaN(NaN)); // true
console.log(isNaN(10)); // false
console.log(isNaN("10")); // false
console.log(isNaN("blue")); // true
console.log(isNaN(true)); // false
尽管有点儿不可思议,但 isNaN()确实也适用于对象。在基于对象调用 isNaN()函数时,会首先调用对象的 valueOf()方法,然后确定该方法返回的值是否可以转换为数值。如果不能,则基于这个返回值再调用 toString()方法,再测试返回值。
有 3 个方法可以把非数值转换为数值:Number()、parseInt()、parseFloat()
Number()方法转换规则:
- 布尔值:true 转换为 1,false 转换为 0
- 数字值:简单的传入传出
- undefined:转换为 NaN
- null: 转换为 0
- 字符串:如果只包含数字,则会去掉最前面的 0 转换为十进制;如果字符串包含有效的十六进制数,则转换为等值的十进制;空字符串转换为 0;如包含上述格式以外的字符,转换为 NaN
- 对象:会首先调用对象的 valueOf()方法,然后确定该方法返回的值是否可以转换为数值。如果不能,则基于这个返回值再调用 toString()方法,再测试返回值。
[搞懂这个规则再结合 NaN 的计算规则就可以完全理解任何数值 / 0 的结果]
parseInt()计算规则:
这个方法有第二个参数,是指定进制规则的。不传默认为十进制。
parseInt()函数在转换字符串时,更多的是看其是否符合数值模式。它会忽略字符串前面的空格,直至找到第一个非空格字符。如果第一个字符不是数字字符或者负号,parseInt()就会返冋 NaN; 也就是说,用 parseInt()转换空字符串会返回 NaN(Number()对空字符返回 0)。如果第一个字符是数字字符,parseInt()会继续解析第二个字符,直到解析完所有后续字符或者遇到了一个非数字字符。
parseFloat()计算规则:
这个方法只解析十进制。
parseFloat()也是从第一个字符开始解析每个字符。而且也是一直解析到字符串末尾,或者解析到遇见一个无效的浮点数字字符为止。也就是说,字符串中的第一个小数点是有效的,而第二个小数点就是无效的了,因此它后面的字符申将被忽略。
(6)String
有 2 个方法可以把非字符串转换为字符串:toString()、String()
除了 undefined 和 null 都可以使用 toString()方法,这个方法接受一个参数,可以指定进制规则。如果可能是 undefined 或者 null,可以用 String()方法。
(7)Object
对象其实就是一组数据和功能的集合。对象可以通过执行 new 操作符后跟要创建的对象类型的名称来创建。
var o = new Object()
Object 的每个实例都具有下列属性和方法:
- Constructor:保存着用于创建当前对象的函数。对于前面的例子而言,构造函数 (constructor) 就是 Object()。
- hasOwnProperty(propertyName):用于检查给定的域性在当前对象实例中 (而不是在实例的原型中) 是否存在。其中,作为参数的属性名 (propertyName) 必须以字符串形式指定(例如:o.hasOwnProperty (“name”) )。
- isProtocypeOf(object):用于检査传人的对象是否是另一个对象的原型。
- propertylsEnumerable(propertyName):用于检查给定的属性是否能够使用 for-in 语句来枚举。与 hasOwnProperty ()方法一样,作为参数的域性名必须以字符串形式指定。
- toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应。
- toString():返回对象的字符串表示。
- valueOf():返回对象的字符串、数值或布尔值表示。通常与 toString()方法的返回值相同。