JavaScript 变量类型

变量类型

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 类型
// 然后再取反,获得正确的值

你可能感兴趣的:(JavaScript 变量类型)