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

  1. explicit: String(x)
  2. implicit: 123 + '3'
  3. 所有原始类型的值转为 string 的结果 naturally as expect
  4. 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

  1. explicit: Boolean(x)
  2. implicit: 条件判断语句、逻辑运算符表达式(|| && !)

以下均返回 false:

Boolean()
Boolean(false)    
Boolean(0)        
Boolean(-0)       
Boolean('')       
Boolean(NaN)      
Boolean(null)     
Boolean(undefined)

不在上面名单的 value 都返回 true,比如 "0""false"[]{}function(){}Symbol()

Numeric conversion

  1. explicit: Number(x)
  2. implicit: 比较操作符、位操作符、数学运算符、单目 + 操作符、loose equality == 操作符
  3. 字符转为数字时,先trim首尾的空格
  4. Symbols不能转为 nubmer,报 TypeError
  5. 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,转换基本步骤:

  1. 判断 input 是否为 primitive, 如果是,则直接返回
  2. Call input.toString(), 结果为 primitive 则返回
  3. Call input.valueOf(), 结果为 primitive 则返回
  4. 如果上述方法都不返回 primitive,则报 TypeError

如果 preferred type 为数字类型,则执行顺序为(3)——> (2)。

  • 例外:单目 + 操作符、loose equality == 操作符触发 default conversion mode,这种情况下大部分内置类型默认采用 numeric 转换
  • 例外: Date 类型默认采用 string 转换。但遇到 - 号,则使用 numeric 转换
  • 例外: null 只能非严格等于 nullundefined
  • 内置类型没有 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