你不知道的JavaScript(中)
1 类型
1.1 js有七种内置类型
1 undefined 2 boolean 3 number 4 string 5 object 6 null 7 symbol
- typeof undefined === "undefined"
- typeof true === "boolean"; // true
- typeof 42 === "number"; // true
- typeof "42" === "string"; // true
- typeof { life: 42 } === "object"; // true
- typeof Symbol() === "symbol"; // true
但是null稍微特殊
typeof null === "object"; // true
所以如果检测一个值是否为null,需要
var a = null;
(!a && typeof a === "object"); // true
1.2 JavaScript 中的变量是没有类型的,只有值才有。变量可以随时持有任何类型的值
换个角度来理解就是,JavaScript 不做”类型强制“。
在对变量执行 typeof 操作时,得到的结果并不是该变量的类型,而是该变量持有的值的类
型,因为 JavaScript 中的变量没有类型。
1.3 undefined && undeclared
undefined 是值的一种。undeclared 则表示变量还没有被声明过。
遗憾的是,JavaScript 却将它们混为一谈,在我们试图访问 "undeclared" 变量时这样报
错:ReferenceError: a is not defined,并且 typeof 对 undefined 和 undeclared 变量都返回
"undefined"。
typeof undefined == "undefined"
typeof undeclared == "undefined"
2 值
简单值(即标量基本类型值,scalar primitive)总是通过值复制的方式来赋值 / 传递,包括
null、undefined、字符串、数字、布尔和 ES6 中的 symbol。
复合值(compound value)——对象(包括数组和封装对象,参见第 3 章)和函数,则总 是通过引用复制的方式来赋值 / 传递。
var a = 2;
var b = a; // b是a的值的一个副本
b++;
a; // 2
b; // 3
var c = [1,2,3];
var d = c; // d是[1,2,3]的一个引用
d.push( 4 );
c; // [1,2,3,4]
d; // [1,2,3,4]
在上述代码中,a,b分别指向 值 的两个复本。a,b的改变互不影响。
c,d分别指向 值 的两个引用,而引用都指向同样的一个对象 [1,2,3],所以c,d的改变是对于所指对象的改变。
function foo(x) {
x.push( 4 );
x; // [1,2,3,4]
// 然后
x = [4,5,6];
x.push( 7 );
x; // [4,5,6,7]
}
var a = [1,2,3];
foo( a );
a; // 是[1,2,3,4],不是[4,5,6,7]
其中,a将 [1,2,3]的引用的复本,传给了变量x。变量x 指向 对象[1,2,3]的引用的复本,可以修改其值。
随后,变量x指向 更改为[4,5,6]的引用,这一操作并不会影响a的引用。
3 原生函数
- String()
- Number()
- Boolean()
- Array()
- Object()
- Function()
- RegExp()
- Date()
- Error()
- Symbol()——ES6 中新加入的!
3.1
new String("abc") 创建的是字符串 "abc" 的封装对象,而非基本类型值 "abc"。
var a = new String( "abc" );
typeof a; // 是"object",不是"String"
a instanceof String; // true
Object.prototype.toString.call( a ); // "[object String]"
3.2 内部属性 [[Class]]
这个属性无法直接访问,
一般通过 Object.prototype.toString(..) 来查看。例如:
Object.prototype.toString.call( [1,2,3] ); // "[object Array]"
Object.prototype.toString.call( /regex-literal/i ); // "[object RegExp]"
4 强制类型转换
将值从一种类型转换为另一种类型通常称为类型转换(type casting),这是显式的情况;隐式的情况称为强制类型转换(coercion)。
也可以这样来区分:类型转换发生在静态类型语言的编译阶段,而强制类型转换则发生在动态类型语言的运行时(runtime)。