JavaScript不一样的数据类型

(一)js数据类型

引自MDN:

最新的 ECMAScript 标准定义了 7 种数据类型:

至今,JS中共上述7种数据类型。这里需要注意,不要将js的内置对象:Date、Array等与数据类型混淆了,这些内置对象和我们自己创建的对象统一属于Object类型。

6中原始类型的值都无法改变。举个栗子,数值1,我们是无法将他改变成2的;字符串的变化实质上也是产生了一个新的字符串,旧的字符串仍然不变。由于这种特性,js会将其存至栈中,按值访问。而引用类型Object内容是可变的,而且大小不固定,所以将它存入堆中,通过地址引用的方式调用。

Boolean类型:表示逻辑,取值truefalse

Number类型:表示数字,和其他语言不同,js只有一种数字类型,是基于IEEE 754标准的双精度64位的值,取值范围(-2^63 - 1 至 2^63 - 1)。此外还有一些特殊标识符:Infinity、-Infinity、NaN。

String类型:表示字符串,由字符(2个字节)组成的一组数据,因此它也具有数组的可遍历、拥有长度属性等特性。

Symbol类型:表示符号类型,ES6新增的数据类型,表示一个唯一值,一般作为对象的key值或者枚举之用,非常适合消除魔法字符串。

Null类型:表示空值,可以理解为一个尚未创建的对象。它虽然是空值,但是却是一个对象,而且Object对象是继承自它,所以它可以说才是真正的对象始祖。

注意:虽然null是一个对象,但是其中的属性都是不可访问的,因此,我们是无法通过代码获取它的属性的。

Undefined类型:表示未定义,一个没有定义的变量或者没有赋予初始值的对象的值就是undefined。这里不要与Null混淆,它不是一个对象。

null === undefined; //false
null == undefined;  //true  
null === null;  //true
undefined == undefined; //true
复制代码

Object类型:表示对象。在计算机科学中, 对象是指内存中的可以被标识符引用的一块区域。在JS中,对象可以被看做是一组属性的集合。JS中以ObjectFunction两个对象为基础,衍生出了现在百花齐放的各种对象,JS的继承、原型等都在这个基础上实现的。


类型判断

由于js弱类型的机制,变量的类型需要我们自己判断。江湖上出现了各种判断方法,下面我们来总结一下。

1.typeof

MDN上推荐的方法。

    let str = 'string';
    let pNum = 11;
    let bRt = true;
    let pSymbol = Symbol('symbol');
    let pObj = {};
    let pArray = [];
    let fun = function () {};

    //typeof
    console.log('字符串', typeof str); //string
    console.log('数字', typeof pNum); //number
    console.log('布尔', typeof bRt); //boolean
    console.log('符号', typeof pSymbol); //symbol
    console.log('null', typeof null); //object
    console.log('undefined', typeof undefined); //undefined
    console.log('对象', typeof pObj); //object
    console.log('数组', typeof pArray); //object
    console.log('函数', typeof fun); //function
复制代码

如上执行结果,对于原始类型(除了null以外),输出结果没问题。但是对于引用类型,输出结果只会是objectfunction,这并非我们预期的结果。

typeof输出的结果包含以下7种:number、boolean、string、symbol、undefined、object、function。

2.instanceof

这种方式只能判断拥有原型的对象,并且只能判断比较的两个对象之间是否属于实例关系(包括继承),不能获取类型。

    console.log('对象', pObj instanceof Object); //true
    console.log('数组是否数组', pArray instanceof Array); //true
    console.log('数组是否对象', pArray instanceof Object); //true
    console.log('函数是否函数', fun instanceof Function); //true
    console.log('函数是否对象', fun instanceof Object); //true
复制代码

需要注意,它会去原型链上去寻找匹配项,例如:pArray instanceof Object结果也是true。该方法用作判断变量是否是某个类的实例非常有效。但是需要注意,这里的比对默认都是在同一个全局环境下比对的。也就是说,在同一个frame下,我们才能得到正确结果。如果在frame1下去判断一个变量是否属于frame2的Object,只会得到false结果。

3.constructor或proto

    console.log('construct');
    console.log('字符串', str.construct === String.construct); //true
    // console.log('数字', typeof pNum); //数字没有construct
    console.log('布尔', bRt.construct === Boolean.construct); //true
    // console.log('符号', typeof pSymbol); //symbol没有construct
    // console.log('null', typeof null); //null无法访问construct属性
    // console.log('undefined', typeof undefined); //undefined无法访问construct属性
    console.log('对象', pObj.construct === Object.construct); //true
    console.log('数组', pArray.construct === Array.construct); //true
    console.log('函数', fun.construct === Function.construct); //true

    console.log('__proto__');
    console.log('字符串', str.__proto__ === String.prototype); //true
    // console.log('数字', typeof pNum); //数字没有prototype
    console.log('布尔', bRt.__proto__ === Boolean.prototype); //true
    // console.log('符号', typeof pSymbol); //symbol没有prototype
    // console.log('null', typeof null); //null无法访问prototype属性
    // console.log('undefined', typeof undefined); //undefined无法访问prototype属性
    console.log('对象', pObj.__proto__ === Object.prototype); //true
    console.log('数组', pArray.__proto__ === Array.prototype); //true
    console.log('函数', fun.__proto__ === Function.prototype); //true
复制代码

原理同2,只是不会再去原型链上查找了,这里固定只对比当前对象的实例。

4.toString

    console.log('字符串', Object.prototype.toString.call(str)); //[object String]
    console.log('数字', Object.prototype.toString.call(pNum)); //[object Number]
    console.log('布尔', Object.prototype.toString.call(bRt)); //[object Boolean]
    console.log('符号', Object.prototype.toString.call(pSymbol)); //[object Symbol]
    console.log('null', Object.prototype.toString.call(null)); //[object Null]
    console.log('undefined', Object.prototype.toString.call(undefined)); //[object Undefined]
    console.log('对象', Object.prototype.toString.call(pObj)); //[object Object]
    console.log('数组', Object.prototype.toString.call(pArray)); //[object Array]
    console.log('函数', Object.prototype.toString.call(fun)); //[object Function]
    console.log('日期', Object.prototype.toString.call(new Date())); //[object Date]
    console.log('window', Object.prototype.toString.call(window)); //[object HTMLDocument]
    console.log('document', Object.prototype.toString.call(document)); //[object global]
复制代码

Object中定义的toString方法,返回的是当前对象的内部属性[[Class]],结果格式为[object Xxx],其中Xxx就是我们判断数据类型的依据,也是内置对象的字符串。

看一下优秀的框架是怎么做的

JQuery

function toType( obj ) {
    if ( obj == null ) {
        return obj + "";
    }

    // Support: Android <=2.3 only (functionish RegExp)
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[ toString.call( obj ) ] || "object" :
        typeof obj;
}
复制代码

原始类型使用typeof,引用类型使用toString。

AngularJs

function isNumber(value) {return typeof value === 'number';}
function isDate(value) {
  return toString.call(value) === '[object Date]';
}
复制代码

也是一样,原始类型使用typeof,引用类型使用toString。

这里其实toString能够完成typeof的所有任务,不知为何以上两个框架会混用。私自猜测可能是因为typeof使用起来更为简洁一点,所以会优先使用typeof。


总结

①boolen、number、string、symbol、function可通过typeof或toString方式判断。

②null、undefined直接通过 ===运算符判断。

③js内置对象,如:Object、Function、Date、Regex等通过toString方式判断。

④自定义类和相应继承类,通过 instanceof判断。


参考:

判断JS数据类型的4种方法

JavaScript 数据类型和数据结构

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

推荐阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,057评论 0 13
  •   引用类型的值(对象)是引用类型的一个实例。   在 ECMAscript 中,引用类型是一种数据结构,用于将数...
    霜天晓阅读 1,014评论 0 1
  • 原文: https://github.com/ecomfe/spec/blob/master/javascript...
    zock阅读 3,343评论 2 36
  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,151评论 0 4
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 2,011评论 0 2