变量类型
JavaScript 中的变量类型分为值类型(又称为简单类型、基本数据类型)以及引用类型。
【值类型】:
- Number
- String
- Undefined
- Null
- Boolean
【引用类型】:
- Object
- Array
- Function
值类型和引用类型的区别
- 存储方式的不同:每声明一个值类型变量,都会在内存中单独分配出一块区域用以保存,变量之间不会相互影响;而引用类型返回的是存储地址,因此若是变量之间的赋值,实际是将地址的引用进行赋值。
// 值类型
var a = 100, b = a;
console.log(a); // 100
console.log(b); // 100
b = 50;
console.log(a); // 100
console.log(b); // 50
// 引用类型
var a = { number: 100 }, b = a;
console.log(a.number); // 100
console.log(b.number); // 100
b.number = 50;
console.log(a.number); // 50
console.log(b.number); // 50
typeof 运算符
typeof 运算符把类型信息当作字符串返回。
var number = 100,
string = "Hello",
boolean = true,
variable,
variable2 = null,
fun = function() {},
object = {},
array = [];
console.log(typeof number); // "number"
console.log(typeof string); // "string"
console.log(typeof boolean); // "boolean"
console.log(typeof variable); // "undefined"
console.log(typeof variable2); // "object"
console.log(typeof fun); // "function"
console.log(typeof object); // "object"
console.log(typeof array); // "object"
- typeof 只能区分值类型:number、string、undefined、boolean。
- 引用类型除函数外,对象和数组都为 object(注意,基本类型中的 null 也为 object)。
- 函数在JS中为一等公民,因此能够被 typeof 识别为 function。
如何区分数组?
- 鸭式辨型法:
var array = [1, 2, 3];
if (typeof array.sort === "function") {
// 思想:判断当前对象是否拥有数组对象专有的 sort 函数。
console.log("haha");
}
// 缺陷
var array = {
data: [],
sort: function() {}
}
if (typeof array.sort === "function") {
// 也能成功执行
console.log("hoho");
}
- Kangax 方案:
var array = [1, 2, 3];
if (Object.prototype.toString.call(array) === "[object Array]") {
// 思想:调用某个值的内置 toString() 方法在所有浏览器中都会返回标准的字符串结果。
// 对于数组来说,返回的字符串为 “[object Array]”.
console.log("haha");
}
// 缺陷:对于自定义对象使用这种方法会存在问题,比如内置 JSON 对象将返回 “[object JSON]”
- isArray() 方法:
var array = [1, 2, 3];
if (Array.isArray(array)) {
// ECMAScript5 将 Array.isArray() 正式引入 JavaScript。
console.log("haha");
}
// 兼容低版本写法
function isArray(value) {
if( typeof Array.isArray === "function") {
return Array.isArray(value);
} else {
return Object.prototype.toString.call(value) === "[object Array]";
}
}
类型转换
JavaScript 是一种弱类型语言,所以无法确定变量保存具体类型的值,并且变量的类型也可以随时发生变换。
转换规则
【示例】:
var a = 100,
b = "50",
c = true,
d = null,
e,
f = function() {},
g = {},
h = [],
i = { data: 1 },
j = [1, 2];
// Number
console.log("Number + String", a + b); // "10050"
console.log("Number + Boolean", a + c); // 101
console.log("Number + Null", a + d); // 100
console.log("Number + Undefined", a + e); // NaN
console.log("Number + Function", a + f); // 100function() {}
console.log("Number + Object(Empty)", a + g); // 100[object Object]
console.log("Number + Array(Empty)", a + h); // 100
console.log("Number + Object", a + i); // 100
console.log("Number + Array", a + j); // 100
// 引用类型
console.log(f.toString()); // function() {}
console.log(g.toString()); // [object Object]
console.log(h.toString()); //
console.log(i.toString()); // [object Object]
console.log(j.toString()); // 1,2
// String
console.log("String + Boolean", b + c); "50true"
console.log("String + Null", b + d); "50null"
console.log("String + Undefined", b + e); "50undefined"
console.log("String + Function", b + f); "50function() {}"
console.log("String + Object", b + g); "50[object Object]"
console.log("String + Array", b + h); "50"
// Boolean
console.log("Boolean + Null", c + d); "1"
console.log("Boolean + Undefined", c + e); "NaN"
console.log("Boolean + Function", c + f); "truefunction() {}"
console.log("Boolean + Object", c + g); "true[object Object]"
console.log("Boolean + Array", c + h); "true"
// Null
console.log("Null + Undefined", d + e); "NaN"
console.log("Null + Function", d + f); "nullfunction() {}"
console.log("Null + Object", d + g); "null[object Object]"
console.log("Null + Array", d + h); "null"
// Undefined
console.log("Undefined + Function", e + f); "undefinedfunction() {}"
console.log("Undefined + Object", e + g); "undefined[object Object]"
console.log("Undefined + Array", e + h); "undefined"
【规则】:
- 所有类型都能够转换为 String 类型。引用类型会调用 toString() 方法进行类型转换。而值类型则将值转换为 String 类型(100 => "100",true => "true")。
- 类型转换遵循向操作数类型优先级高的一方转换的原则。例如,Number 和 String 相加,将 Number 转换为 String。
- Boolean 和 Null 类型可以转换为 Number 类型(true:1,false:0,null:0)。
- Undefined 类型无法转换为 Number 类型,因此和 Number 类型执行加算术运算时会得到 NaN。
【注意】:当操作数中不存在 String 类型,+ 表示算术运算中的加法运算,因此在进行类型转换时,会转换为 Number 类型。若存在 String 类型,+ 表示连字符操作,因此会转换为 String 类型。在判断类型转换时,必须要明确当前具体要执行的操作。
【问】:为什么 Number 类型和引用类型相加时,最后的结果却是 String?按照上述规则中的“类型转换遵循向操作数类型优先级高的一方转换的原则”,不应该是将引用类型转化为 Number 类型吗?
【答】:引用类型在执行 + 操作时,会调用其自身的 toString() 方法,此时引用类型已经转换为 String。而 String 的优先级大于 Number,会将 Number 转换为 String,因此最后的结果是 String。
【Boolean 类型转换规则】:
类型 | true | false |
---|---|---|
String | 非空字符串 | 空字符串 "" |
Number | 非 0 和 NaN | 0 和 NaN |
Undefined | 不适用 | Undefined |
Null | 不适用 | Null |
Object | 任何对象 | 不适用 |
Array | 任何数组 | 不适用 |
Function | 任何函数 | 不适用 |
【示例】:
var a = 100,
a_2 = 0,
b = "50",
b_2 = "",
c = true,
c_2 = false,
d = null,
e,
f = function() {},
g = {},
h = [],
i = { data: 1 },
j = [1, 2];
console.log(!!a); // true
console.log(!!a_2); // false
console.log(!!b); // true
console.log(!!b_2); // false
console.log(c); // true
console.log(c_2); // false
console.log(!!d); // false
console.log(!!e); // false
console.log(!!f); // true
console.log(!!g); // true
console.log(!!h); // true
console.log(!!i); // true
console.log(!!j); // true
强制类型的场景
- 字符串拼接
- == 等于运算符
- if () 条件判断
- 逻辑运算符
小技巧:转换为 Boolean 类型
【示例】:
var a = 100;
a = !!a;
// 先通过取反操作,将其转换为 Boolean 类型
// 然后再取反,获得正确的值