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()方法的返回值相同。
2. 引用类型
构造函数本身就是一个函数,只不过该函数是出于创建新对象的目的而定义的。
var person = new Object();
2.1 Object类型
(1)创建对象
创建Object示例的方法有两种:
第一种是使用new操作符后跟Object构造函数。
var person = new Object();
第二种是使用对象字面量表示法:
var person = {
name: 'Peggy7',
age: 25
}
var person = {}与var person = new Object()是等价的。
(2)访问对象的属性
访问对象属性可以用点表示法和方括号表示法。
person.name
person['name']
两者看上去没有区别,但方括号表示法可以通过变量的访问属性,如果属性名中包含会导致语法错误的字符,或者属性名使用的是关键字或保留字,也可以使用方括号表示法。通常,除非使用变量来访问属性,否则建议使用点表示法。
2.2 Array类型
(1)创建数组
创建数字也有两种方法:
第一种是使用new操作符后跟Array构造函数。
var colors = new Array(3);
var colors2 = new Array('red', 'blue', 'green');
如果传入的是数值则表示创建一个长度为该数值的数组,也可直接传递数组中要保存的项。
第二种是使用数组字面量表示法:
var colors = ['red', 'blue', 'green'];
数组的length属性不光是只读的。
(2)监测数组
Array.isArray()方法可以准确的监测出一个值是否是数组。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。