JavaScript Data Types and Type Conversion
JS 是一种 weakly-typed 语言。
- 基本类型: String(”John Doe”),Numbers(3.14),Boolean(true/false),Symbol 和 Object。
- Function、Array、Date、RegExp 都是 objects
- 有2种不含 value 的类型:undefined,null
constructor Property
该性质返回所有JS变量的 constructor 函数。
"John".constructor // Returns function String() { [native code] }
(3.14).constructor // Returns function Number() { [native code] }
false.constructor // Returns function Boolean() { [native code] }
[1,2,3,4].constructor // Returns function Array() { [native code] }
{name:'John', age:34}.constructor // Returns function Object() { [native code] }
new Date().constructor // Returns function Date() { [native code] }
function () {}.constructor // Returns function Function(){ [native code] }
可以用来判断一个变量类型是否是 Array,判断 Date 方法同。
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
// 用 prototype 类似
function isArray(myArray) {
return Object.prototype.toString.call(myArray) === '[object Array]'
}
Undefined
var person;
未初始化的变量 person 其值是 undefined,typeof 结果也是 undefined。
下列情况会返回 undefined:
- 访问未定义的变量
- 没有定义
return
表达式的函数隐式返回 return
表达式没有显示的返回值- 访问不存在的属性
- 任何被设置为
undefined
的变量
Null
null
表示一个不再指向任何内存空间地址的变量。与 undefined 不同,typeof null
的结果是 object
。
null == undefined; // true
null === undefined; // false
可以用 null 来清空一个 object 变量。当然用 undefined 来清空也是可以的,但是注意结果如前所述是有区别的。
null
is for objects, undefined
is for variables, properties, and methods.
Test if an object exists
测试一个对象是否存在,必须如下先检查该对象是否被定义了。
if (typeof myObj !== "undefined" && myObj !== null)
if (myObj !== null && typeof myObj !== "undefined") // 这样写会 throw error exception,两句的区别见下面
var person = {};
typeof person; // object
person.valueOf(); // [object Object]
(person !== null); // true
typeof persons; // undefined
(persons !== null); // 浏览器报错,ReferenceError: Can't find variable: persons
Type Conversion
JS 类型转换分为 implicit 和 explicit。开发者通过一些函数进行的转换称为 explicit type coercion。
因为JS变量是 dynamic 类型,可以在不同类型间自动变换,这种转换称为 implicit type coercion。
JS 中类型转换一共有3种规则:to string,to number,to Boolean。
推荐查看:JavaScript type coercion explained
String conversion
- explicit:
String(x)
- implicit:
123 + '3'
- 所有原始类型的值转为 string 的结果 naturally as expect
- Symbol 只能进行 explicit 转换
注意:在JS输出时,会自动调用 toString() 方法。
String({name:"Fjohn"}) // "[object Object]"
String([1,2,3,4]) // "1,2,3,4"
String(new Date()) // "Fri Mar 16 2018 11:20:16 GMT+0800 (中国标准时间)"
String(123) // "123"
String(true) // "true"
String(null) // "null"
String(undefined) // "undefined"
Boolean conversion
- explicit:
Boolean(x)
- implicit: 条件判断语句、逻辑运算符表达式(
||
&&
!
)
以下均返回 false:
Boolean()
Boolean(false)
Boolean(0)
Boolean(-0)
Boolean('')
Boolean(NaN)
Boolean(null)
Boolean(undefined)
不在上面名单的 value 都返回 true,比如 "0"
,"false"
,[]
,{}
,function(){}
,Symbol()
。
Numeric conversion
- explicit:
Number(x)
- implicit: 比较操作符、位操作符、数学运算符、单目
+
操作符、loose equality==
操作符 - 字符转为数字时,先trim首尾的空格
- Symbols不能转为 nubmer,报 TypeError
- Date 转换可以使用
Number()
, 或者getTime()
函数,得到的是 milliseconds since January 1, 1970, 00:00:00
Number(null) // 0
Number(undefined) // NaN
Number(true) // 1
Number(false) // 0
Number("true") // NaN
Number(" 12 ") // 12
Number("-12.34") // -12.34
Number("\n") // 0
Number(" ") // 0
Number([]) // 0
Number({}) // NaN
Number("") // 0
Number(" 12s ") // NaN
Number("99 88") // NaN
Number('-Infinity') //-Infinity
栗子
两个数字式字符串做比较:
"2" > "12" // true,because (alphabetically) 1 is less than 2
2 < "12" // true,"12" 转换成数字12进行了比较
为了保证正确的结果,在比较之前,需要把变量转换成合适的类型。
age = Number(age);
if (isNaN(age)) {
voteable = "Error in input";
} else {
voteable = (age < 18) ? "Too young" : "Old enough";
}
单目运算符 +
,把一个值转换成 Number 类型。
-
减号时,表示负数 reverse the sign.
var y = "5"; // y is a string
var x = + y; // x is a number
var z = "apple";
x = +z; // x is NaN
Object 的类型转换
对象通过内置 ToPrimitive(x, preferred type)
方法先转为 primitive value,然后转为 final type,其中 preferred type 是 可选的。
假设 preferred type 为 string,转换基本步骤:
- 判断 input 是否为 primitive, 如果是,则直接返回
- Call input.toString(), 结果为 primitive 则返回
- Call input.valueOf(), 结果为 primitive 则返回
- 如果上述方法都不返回 primitive,则报 TypeError
如果 preferred type 为数字类型,则执行顺序为(3)——> (2)。
- 例外:单目
+
操作符、loose equality==
操作符触发 default conversion mode,这种情况下大部分内置类型默认采用 numeric 转换 - 例外: Date 类型默认采用 string 转换。但遇到
-
号,则使用 numeric 转换 - 例外: null 只能非严格等于 null 或 undefined
- 内置类型没有
valueOf()
方法或者调用此方法返回对象本身的,则继续进行 string 转换 - 单目
+
操作符优先级高于加符运算符
var a = new Date ()
var str = a.toString() // str: Thu Sep 20 2018 17:04:30 GMT+0800 (中国标准时间)
var num = a.valueOf() // num: 1537434270206
a == str // true
a == num // false
a - str // NaN
a - num // 0,since '-' operator explicitly triggers numeric conversion, not a default one