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 类型
// 然后再取反,获得正确的值
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容