一、JS数据类型分类

  1.基本数据类型

    (1)Number 数字

    (2)String 字符串

    (3)Boolean 布尔值

    (4)null 空对象指针

    (5)undefined 为定义

    (6)symbol (es6新增,表示独一无二的值)

    (7)bigint(ES10新增,表示比number数据类型支持的范围更大的整数值)

    注意:NaN是Number中的一种特殊数值,不是一种数据类型

  2.引用数据类型

    object,array和function都是object的子类型

  3.基本数据类型和引用数据类型的区别

    (1)声明变量时内存分配不一样

      基本数据类型:在栈中,因为占据空间是固定的,可以将他们存在较小的内存中-栈中,这样便于迅速查询变量的值

      引用数据类型:存在堆中,栈中存储的变量,只是用来查找堆中的引用地址。

       理由:引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响

    (2)不同的内存分配带来不同的访问机制

      在javascript中是不允许直接访问保存在堆内存中的对象的,所以在访问一个对象时,首先得到的是这个对象在堆内存中的地址,然后再按照这个地址去获得这个对象中的值,这就是传说中的按引用访问。 而基本数据类型的值则是可以直接访问到的。

    (3)复制变量时的不同

      基本数据类型:在将一个保存着原始值的变量复制给另一个变量时,会将原始值的副本赋值给新变量,此后这两个变量是完全独立的,他们只是拥有相同的value而已。

      引用数据类型:在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量, 也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。 (这里要理解的一点就是,复制对象时并不会在堆内存中新生成一个一模一样的对象,只是多了一个保存指向这个对象指针的变量罢了)

    (4)参数传递的不同

       基本数据类型:只是把变量的值传递给参数,之后这个参数和变量互不影响

      引用数据类型:传递是对象在堆内存里面的地址,他们指向同一个对象。

二、数据类型的判断方式

  1.typeof

    typeof返回一个表示数据类型的字符串,返回结果包括:number、boolean、string、symbol、object、undefined、function等7种数据类型,但不能判断null、array等

  2.instanceof

    instanceof 是用来判断a是否为b的实例,表达式为:a instanceof b,如果a是b的实例,则返回true,否则返回false。instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性,但它不能检测null和 undefined   

  3.constructor

    constructor作用和instanceof非常相似。但constructor检测 object与instanceof不一样,还可以处理基本数据类型的检测。不过函数的 constructor 是不稳定的,这个主要体现在把类的原型进行重写,在重写的过程中很有可能出现把之前 的constructor给覆盖了,这样检测出来的结果就是不准确的。

  4.object.prototype.tostring.call() :是最准确最常用的方式。

代码示例:

Object.prototype.toString.call();               // [object String]

Object.prototype.toString.call(1);              // [object Number]

Object.prototype.toString.call(true);           // [object Boolean]

Object.prototype.toString.call(undefined);      // [object Undefined]

Object.prototype.toString.call(null);           // [object Null]

Object.prototype.toString.call(new Function()); // [object Function]

Object.prototype.toString.call(new Date());     // [object Date]

Object.prototype.toString.call([]);             // [object Array]

Object.prototype.toString.call(new RegExp());   // [object RegExp]

Object.prototype.toString.call(new Error());    // [object Error]

三、JS数据类型转换

  1.强制转换

    (1)toPrimitive(obj,type)转换为原始值

      toPrimitive对基本数据类型不发生转换处理,只针对引用数据类型,作用是将引用数据类型转换为基本数据类型。ToPrimitive运算符有两个参数,第一个参数obj是需要转换的对象,第二个参数type是期望转换为的原始数据类型(可选)

      对于参数2 type的说明:

        type=String,首先调用obj的toString方法,如果为原始值则return,否则调用obj的valueOf方法,如果为原始值则return,否则抛出TypeError异常

        type=Number,首先调用obj的valueOf方法,如果为原始值则return,否则调用obj的toString方法,如果为原始值则return,否则抛出TypeError异常

        type参数为空,如果obj是Date对象,则type=String,其它情况把type=Number处理

    (2)toString

      返回一个表示该对象的字符串,每个对象都有toString方法,当对象被表示为文本值时或者当以期望字符串的方式引用对象时,该方法自动调用

var obj={}
console.log(obj.toString())//[object Object] var arr=[1,"111"]
console.log(arr.valueOf())//数组本身
console.log(arr.toString())//1,111
console.log(arr.toLocaleString())//1,111

     (3)valueOf

      Javascript调用valueOf方法来把对象转换成原始类型的值(数值、字符串、布尔值)。某些情况会被自动调用

      array 数组的元素被转换为字符串,这些字符串由逗号分隔,连接在一起。其操作与 array.tostring 和 array.join 方法相同。

      boolean boolean 值。

      date 存储的时间是从 1970 年 1 月 1 日午夜开始计的毫秒数 utc。

      function 函数本身。

      number 数字值。

      object 返回"[object object]",前一个object标记基础类型,后一个object标记子类型

      string 字符串值。

      math 和 error 对象没有 valueof 方法。

var str="我是string";
var num=5;
var date=new Date();
var obj={
name:"cc",
age:16
}
console.log(str.valueOf())//我是string
console.log(num.valueOf())//5
console.log(date.valueOf())//1574577999115
console.log(obj.valueOf())//{name: "cc", age:16}

    (4)Number()

       null==》0、undefined==》NaN、true==》1、false==》0 

      字符串转换时遵循数字常量规则,如果有不是数字的内容则转换失败返回 NaN

Number(null);       //0
Number(undefined); //NaN
Number(true); //1
Number(false); //0
Number('1'); //1
Number('a'); //NaN

    (5)String()

      null、undefined、true、false都加上引号

      数字转换遵循通用规则,溢出将以指数形式或者无穷大(Infinity)

String(null)                 //"null"
String(undefined) //"undefined"
String(true) //"true"
String(1) // '1'
String(-1) // '-1'
String(0) // '0'
String(-0) // '0'
String(Math.pow(1000,10)) // '1e+30'
String(1E+400) // 'Infinity'
String(-Infinity) // '-Infinity'
String({}) // '[object Object]'
String([1,[2,[3,4]],['a']) // '1,2,3,4,a'
String(function (){return 0}) //function({return 0})

    (6)Boolean

      undefined、null、0、+0、-0、NaN、空字符串转换为false,其余都为true

Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true

  2.隐式转换

 

四、数据类型面试题

  1.js中typeOf数据类型分别输出什么

console.log(typeof 1);//Number
console.log(typeof NaN);//Number
console.log(typeof '1');//String
console.log(typeof null);//Object
console.log(typeof undefined);//undefined
console.log(typeof true);//Boolean
console.log(typeof false);//Boolean
console.log(typeof {});//Object
console.log(typeof []);//Object
console.log(typeof function(){var a=1});//function

    特别注意,null、空对象、空数组的结果都是Object,function的结果就是function

  2.null和undefined有什么区别

    一句话概括:undefined是未定义的,null是定义了但是为空。如果对他俩进行==判断,结果为true。用===判断,结果为false

  3.==和===有什么区别

    简单来说: == 代表相同, ===代表严格相同

     理解: 当进行双等号比较时候: 先检查两个操作数数据类型,如果相同, 则进行===比较, 如果不同, 则愿意为你进行一次类型转换, 转换成相同类型后再进行比较(如何转换看上面的图片), 而===比较时, 如果类型不同,直接就是false.

    操作数1 == 操作数2, 操作数1 === 操作数2

    比较过程:

      双等号==:

        (1)如果两个值类型相同,再进行三个等号(===)的比较

        (2)如果两个值类型不同,也有可能相等,需根据以下规则进行类型转换在比较:

            1)如果一个是null,一个是undefined,那么相等

            2)如果一个是字符串,一个是数值,把字符串转换成数值之后再进行比较

      三等号===:

        (1)如果类型不同,就一定不相等

        (2)如果两个都是数值,并且是同一个值,那么相等;如果其中至少一个是NaN,那么不相等。(判断一个值是否是NaN,只能使用isNaN( ) 来判断)

         (3)如果两个都是字符串,每个位置的字符都一样,那么相等,否则不相等。

         (4)如果两个值都是true,或是false,那么相等

         (5)如果两个值都引用同一个对象或是函数,那么相等,否则不相等

         (6)如果两个值都是null,或是undefined,那么相等

  4.请说出以下代码的执行结果和理由(区分算术运算符和字符串拼接)

console.log(1 + 'true')//‘1true’
console.log(1 + true)//2
console.log(1 + undefined)//NaN
console.log(1 + null)//1

    console.log(1 + 'true')//‘1true’【字符串拼接,会把其他数据类型转为字符串然后拼接】
    console.log(1 + true)//2 【加法运算会把其他数据类型转为数字再进行加法运算】
  5.请说出以下代码的执行结果和理由(关系运算符)

console.log('2'>10)//false
console.log('2'>'10')//true
console.log('abc'>'a')//false
console.log('abc'>'aad')//true
console.log(NaN == NaN )//false
console.log(undefined == null )//true

  console.log('2'>10)//false 【关系运算符只有一边是字符串时,会把其他数据类型转为数字,然后比较】

  console.log('2'>'10')//true 【如果两边都是字符串,同事转成字符对应的编码值进行比较】

  console.log('abc'>'a')//false 【如果是多个字符,从左到右依次比较,先比较‘a’和‘b’,如果不等直接出结果】ps:大小比较的是字符的ASCII码值

  console.log('abc'>'aad')//true【如果相等,则比较第二个字符,根据相等于否得出结果】

  console.log(NaN == NaN )//false 【NaN和任何数据比较都是false】

  console.log(undefined == null )//true【undefined和null使用==判定相等,与自身判定也相等】

  6.请说出以下代码的执行结果和理由(复杂数据类型)

console.log([1,2] == '1,2')//true
console.log([1,2].valueOf())// [1,2]
console.log([1,2].toString())// 1,2 var a={}
console.log(a == '[object Object]')//true
console.log(a.valueOf().toString())//[object Object]

  当对象和字符串比较时先调用valueOf()再调用toString方法,然后再进行比较

  下面看一道进阶题:

var a=???
if(a == 1 && a == 2 && a == 3){
console.log(3)
}
如何填写a,使得函数打印出3

  小炉:乍一看,a怎么可能等于1、2、3呢,这题有问题叭!

  前端大佬:非也非也,要知道,在数据类型的比较中,有的可以执行valueOf、toString方法的,突破口就在这里,那么我们重写他的方法,就可以实现改变a值。不多说了,直接上代码:(其他方案传送门)

var a={
i:0,
valueOf:function(){
return ++a.i
}
}
if(a == 1 && a == 2 && a == 3){
console.log(3)
}

  7.请说出以下代码的执行结果和理由(逻辑非隐式转换和关系运算符隐式转换)

代码(1)
console.log([]==0)//true
console.log(![]==0)//true

代码(2)
console.log([]==![])//true
console.log([]==[])//false

代码(3)
console.log({}==!{})//false
console.log({}=={})//false

  首先,你要知道,关系运算符将其他数据类型转成数字,逻辑非:将其他数据类型使用boolean转为布尔类型。

  代码(1)

  [].valueOf.toString()得到空串,空串转为数字是0,所以判断[]==0是true
  逻辑非优先级高于关系运算符,所以![]先是空数组转为布尔true,然后取反是false。0转为布尔也是false所以判断![]==0是true

  代码(2)

  逻辑非优先级高于关系运算符,所以![]先是空数组转为布尔true,然后取反是false。然后是空数组转变得到空串,字符串和布尔进行==比较,将他们二者转为数字进行比较。所以都为0,判定最后结果为true。

  console.log([]==[])//false 因为是引用数据类型,栈中存的是地址,所以不相等

  代码(3)

  逻辑非优先级高于关系运算符,先执行{}.valueOf.toString()得到'[object Object]',对他取反为false,然后将他和空对象都数字化,然后得到0==0,判定他们相等,所以结果为true。

  console.log({}=={})//false 因为是引用数据类型,栈中存的是地址,所以不相等

五、总结

  1.数据类型分为基本数据类型(7种,ES10新增bigint)和引用数据类型(Object和他的子类型array、function)

  2.有四种判断方式,typeOf、instanceOf、constructor、object.prototype.tostring.call()

  3.数据类型有强制转换和隐式转换(面试题考点)

  4.总体来说,需要记的东西很多。多练多做题才更熟悉

参考文档:https://www.cnblogs.com/c2016c/articles/9328725.html

      https://blog.csdn.net/itcast_cn/article/details/82887895

JS的数据类型你真的懂了吗的更多相关文章

  1. 你真的懂ajax吗?

    前言 总括: 本文讲解了ajax的历史,工作原理以及优缺点,对XMLHttpRequest对象进行了详细的讲解,并使用原生js实现了一个ajax对象以方便日常开始使用. damonare的ajax库: ...

  2. 你真的懂 ajax 吗?

    前言 总括: 本文讲解了ajax的历史,工作原理以及优缺点,对XMLHttpRequest对象进行了详细的讲解,并使用原生js实现了一个ajax对象以方便日常开始使用. damonare的ajax库: ...

  3. 程序猿修仙之路--数据结构之你是否真的懂数组? c#socket TCP同步网络通信 用lambda表达式树替代反射 ASP.NET MVC如何做一个简单的非法登录拦截

    程序猿修仙之路--数据结构之你是否真的懂数组?   数据结构 但凡IT江湖侠士,算法与数据结构为必修之课.早有前辈已经明确指出:程序=算法+数据结构  .要想在之后的江湖历练中通关,数据结构必不可少. ...

  4. 你真的懂Redis的5种基本数据结构吗?

    摘要: 你真的懂Redis的5种基本数据结构吗?这些知识点或许你还需要看看. 本文分享自华为云社区<你真的懂Redis的5种基本数据结构吗?这些知识点或许你还需要看看>,作者:李子捌. 一 ...

  5. [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?

    你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...

  6. JavaScript知识 一、JS的数据类型

    一.JS的数据类型 1.基本类型 JS共有5大基本类型,分别是: 1)Undefined.他只有一个值:undefined.如果一个变量被定义但是没有给他赋值,那么这个时候系统会默认给这个变量赋值为u ...

  7. JS中数据类型及原生对象简介

    js是一种专门设计用来给网页增加交互性的编程语言,它的技术体系包含了一下几个方面: 1.JavaScript核心语言定义:包括数据类型,变量,常量,运算符,语句等. 2.原生对象和内置对象 3.浏览器 ...

  8. 每日学习心得:Js基本数据类型常用方法扩展

    2014-02-17 前言: 节后的第一周上班,整个状态调整的还不错,已完全进入正常的工作状态.这一周主要还是对年前项目存在的一些问题进行完善.修整,基本上没有做大的改动.这里就把项目中经常用到的一些 ...

  9. 【转】was mutated while being enumerated 你是不是以为你真的懂For...in... ??

    原文网址:http://www.jianshu.com/p/ad80d9443a92 支持原创,如需转载, 请注明出处你是不是以为你真的懂For...in... ??哈哈哈哈, 我也碰到了这个报错 . ...

随机推荐

  1. 关于Graph Convolutional Network的初步理解

    为给之后关于图卷积网络的科研做知识积累,这里写一篇关于GCN基本理解的博客.GCN的本质是一个图网络中,特征信息的交互+与传播.这里的图指的不是图片,而是数据结构中的图,图卷积网络的应用非常广泛 ,经 ...

  2. 解Bug之路-记一次JVM堆外内存泄露Bug的查找

    解Bug之路-记一次JVM堆外内存泄露Bug的查找 前言 JVM的堆外内存泄露的定位一直是个比较棘手的问题.此次的Bug查找从堆内内存的泄露反推出堆外内存,同时对物理内存的使用做了定量的分析,从而实锤 ...

  3. 03 . Django之腾讯云短信

    简介 由于项目在注册.登录.找回密码 时需要发送短信验证的功能,我们使用腾讯云短信做. 为什么要用腾讯云短信呢? 因为注册就送 100条免费短信 的额度. 注册腾讯云 注册一个腾讯云账户,腾讯云中提供 ...

  4. 使用PyQtGraph绘制图形(2)

    采用addplot()方法将多个图形添加到一个窗口. 首先利用numpy模块创建两个随机数组,用来作为图形绘制的数据: import pyqtgraph as pg import numpy as n ...

  5. 深入理解Js数组

    深入理解Js数组 在Js中数组存在两种形式,一种是与C/C++等相同的在连续内存中存放数据的快数组,另一种是HashTable结构的慢数组,是一种典型的字典形式. 描述 在本文中所有的测试都是基于V8 ...

  6. Codeforces Round #647 (Div. 2)

    Problem A https://codeforces.com/contest/1362/problem/A 判断x/y是不是2的k次方, 如果是 k/3 + (k%3)/2 + (k%3%2)即为 ...

  7. (三)利用@DataProvider传递参数

    具体实现如下: @DataProvider(name="couponListData") public Object[][] couponListData(){ //自己定义Obj ...

  8. 如何开发一个自己的npm包

    目录 一.初始化npm包 二.新建自己的工具类 三.新建入口文件index.js 四.编写单元测试 五.登录仓库 六.发布包 七.安装使用 八.删除包 一.初始化npm包 npm init 运行输入包 ...

  9. Java并发--ReentrantLock原理详解

    ReentrantLock是什么? ReentrantLock重入锁,递归无阻塞的同步机制,实现了Lock接口: 能够对共享资源重复加锁,即当前线程获取该锁,再次获取不会被阻塞: 支持公平锁和非公平锁 ...

  10. cc31a_demo--CppPrimer_静态成员与继承-在派生类中访问基类中的static成员的方法

    //*基类中的static成员,在整个继承层次中只有一个实例 //*在派生类中访问基类中的static成员的方法 //1.基类名::成员名 //2.子类名::成员名 //3.对象.成员名 //4.指针 ...