JavaScript中数据类型和类型判断

数据类型

首先明确ECMAscript中的数据类型分为两种,基本类型(7钟)和引用类型(1种)

基本类型:(又称简单数据类型)7种,未定义类型(Undefined),对空类型(Null),布尔类型(Boolean),数字类型(Number),字符串(String),符号类型(Symbol),BigInt;都是按值访问的,即将一个基本类型的数据赋值给另外一个变量,是将元数据拷贝一份赋值的,两变量之间互不影响。

引用类型:引用类型的值(对象)是应用类型的一个实例,在ECMAScript中,应用类型是一种数据结构,用于将数据和功能绑定在一起。它也常被称为类,虽然这种称呼并不妥当。引用类型有时候也被称为对象定义,因为它描述的是一类对象所具有的属性和方法。 除过对象类型都是引用类型,即保存在内存中的对象,按引用访问,即将一个引用类型的地址赋值给另一个变量,这两个变量的值是相同的相当于指针,都指向同一块内存空间, 操作该变量等于操作该变量指向的内存空间的值,当其中一个变量改变时,原变量也会随之改变。如Object,Function,Date,RegExp,Array, Map,Set........但是Object是引用变量的本质

小可耐们注意啦~~~ 引用类型与基本包装类型的主要区别就是对象的生存期。使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁。这意味着我们不能在运行时为基本包装类型添加属性和方法。


类型对比

基本类型主要是把值存储在内存中;基础类型赋值会重新创建一个基础值;它们的值直接存储在变量访问的位置。这是因为这些原始类型占据的空间是固定的,所以可将他们存储在较小的内存区域 – 栈中。这样存储便于迅速查寻变量的值。

引用类型把值存储在内存中,堆内存的地址存储在栈内存中;引用类型赋值只是把堆内存的地址赋值给新变量.也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。这是因为:引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。

堆和栈有啥区别?

堆:堆为队列优先,先进先出(FIFO),使用二级缓存,生命周期与虚拟机的GC算法有关(并不是引用为空就立即被GC),调用速度相对较低。

栈:栈为先进后出(FILO),使用一级缓存,被调用时通常处于存储空间中,调用后被立即释放。


变量类型判断

1. 使用typeof检测

格式: typeof  变量名

返回值:‘number’,‘string’,‘boolean’,‘undefined’,‘symbol’, ‘object’,只有这六种返回类型,剩下均被检测为‘object’。

注意:而且typeof null === 'object' (JS 设计初的bug)

总结:简单,对基础类型检测性能好;

2. 使用instanceof检测

格式:变量名  instanceof  数据类型

判断参照对象(引用类型)的prototype属性所指向的对象书否在被行测对象的原型链上,比如 

class Person{

    constructor(name) {

        this.name = name;

    }

 }

let p  = new Person("张三");

按照描述就是Person的prototype属性所指向的原型对象是否存在于p的原型链中。

这种判断方式,undefined和null被检测为object

总结:能检测出引用类型;不能检测出基本类型;

3. 使用constructor检测

constructor本来是原型链上的属性,指向构造函数,但是根据实例对象寻找属性的顺序,若实例对象上没有实例属性或方法,就去原型链上寻找,因此,实例对象也是能够使用constructor属性的。

除了undefined和null,其他类型的变量均能使用constructor判断出类型,只不过使用constructor是不保险的,因为constructor属性是可以被修改的,会导致检测出的结果不正确。比如

function f() { }

f.prototype = new Array();

let ff = new f();

console.log(ff.constructor==true);  //true

使用instanceof和constructor,被判断的array必须是当前页面声明的,比如,一个页面(父页面)有一个框架,框架中引用了一个页面(子页面),在子页面中生命了一个Array,并将其赋值给父页面的一个变量,这是判断该变量,Array == object.constructor;会返回false;

原因:

1、array属于引用型数据,在传递过程中,仅仅是引用地址的传递。

2、instanceof操作符是假定只有一个全局执行环境,如果网页中包含多个框架,就会存在两个以上不同的全局执行环境,从而存在两个以上不同版本的Array构造函数。如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。

    为了解决这个问题,可以使用ES5中新增的方法 Array.isArray() 方法,这个方法的目的是最终确定某个值到底是不是数组,而不管它是在哪个全局执行环境中创建的。

总结:基本能检测所有的类型(除了null和undefined);constructor易被修改,不可靠

4.使用Object.prototype.toString.call()检测

ECMA对Object.prototype.toString的解释:

Object.prototype.toString( )

When the toString method is called, the following steps are taken:

1. Get the [[Class]] property of this object. 获取对象的类名(对象类型)

2. Compute a string value by concatenating the three strings “[object “, Result (1), and “]”.  然后将[object  获取的类名] 组合

3. Return Result   返回组合结果

这种方式解决了instanceof存在的跨页面问题,也解决了属性检测方式所存在的问题,nice~~~~

总结:所有类型都能检测;写起来比较繁琐,性能不如 typeof 好;


例子

下面定义了常见的变量类型

let num = 7;         let num2 = new Number(7);

let str = "hello";      let str2 = new String("hello");

let boo = true;       let boo2 = new Boolean(true);

let arr = [1, 2, 3, 4];

let json = { name: "dingdang", age:20};

let func = function() {console.log("this is function")};

let und = undefined;

let nul = null;

let date = new Date();

let reg = /^[a-zA-Z]{5,20}$/;

let error = new Error();

let map = new Map([ ['name', '张三'], ['title', 'Author']]);

let set = new Set(['red', 2, 'blue', 4]);

运行结果见下图:

宽宽的图

                                   ~~~~~听大神说写博客可以成为小仙女~~~~~

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

推荐阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,148评论 0 13
  • 1.通过typeof可以判断处几种基本数据类型Boolean,number,string,null,undefin...
    舟渔行舟阅读 645评论 0 1
  • 我的妈妈是个既温柔又暴躁的妈妈。一双弯弯的眉毛下有一双黑宝石般的大眼睛,挺挺的鼻子下有一张能说会道的小嘴,一头乌黑...
    王佳睿阅读 206评论 0 1
  • 固体制剂 散剂 特点 1粒径小,比表面积大,易分散和起效快 2外用覆盖面积大,兼具保护,收敛等作用 3制备工艺简单...
    莹涛_石头记阅读 533评论 0 0
  • 小晓是个很内向的姑娘,因为内向而不自信,不敢争不敢抢,在公司里也是最低级的存在。好像谁都可以指示她,哪怕这些事本就...
    莴笋姑娘阅读 433评论 0 1