数据类型的分类

JS中的数据类型有七中原始数据类型:

  • 原始数据类型[值类型/基本数据类型]:
    • number 数字
    • string 字符串
    • boolean 布尔
    • null 空对象指针
    • undefined 未定义
    • symbol 唯一值
    • bigint 大数
  • 对象类型[引用数据类型]
    • object
      • 标准普通对象 object
      • 标准特殊对象 Array、RegExp、Date、Math、Error...
      • 非标准特殊对象 Number、String、Boolean...
      • 可调用/执行对象 函数Function

非标准特殊对象

除了null和undefined每个原始值类型都有一个自己对应的对象类型值

Symbol

Symbol是唯一值,他是不能通过New操作符进行创建的,每次执行Symbol都是创建一个唯一值,下方代码A和B虽然看起来是一样的但却不相等的两个值。假如如果把C=A这样把A的值赋给C,那么A和C肯定是相等的

let A = Symbol('i东东')
let B = Symbol('i东东')
let C = A 
console.log(A === B); // false
console.log(A === C); // true

应用场景

  • 给对象设置唯一值的属性名,在ES6之前对象的属性名只能是字符串类型,但是新增了ES6之后对象的属性名增加了可以用Symbol类型的属性名。
  • Map新的数据结构:可以允许属性名是对象
  • Symbol.asyncIterator/iterator/hasInstance/toStringTag...是某些JS知识底层实现机制
  • 在派发行为标识进行统一管理的时候,可以基于Symbol类型的值,保证标识的唯一性

用字符串和数字类型的都可以取到值,name就可以认为他们的属性名是字符串类型的 

下方代码console.log([Symbol('AA')])是无法取到值的,因为这个相当于创建了一个新的唯一值,用新的唯一值去访问是不对应的,正确的方法应该是创建一个唯一值,再把这个唯一值作为属性去访问。

let key = Symbol('88')
let obj = {
  num: 100,
  10:'数字',
  [Symbol('AA')]:'Symbol类型的属性名', // 在大括号中加Symbol语法要求必须加大括号
  [key]:400
}
console.log(obj[Symbol('AA')]); // undefined
console.log(obj[key]); // 400说

一个对象的属性名是不能重复的,用唯一值做属性的好处就是,他是不会重复的

let obj = {
  [Symbol('AA')]: 100,
  [Symbol('AA')]: 100,
  // 这两个是不同的两个值
}

BigInt 大数类型

JS中的最大安全数 Number.MAX_SAFE_INTEGER = 9007199254740991

JS中的最小安全数 Number.MIN_SAFE_INTEGER = -9007199254740991

超过安全数后,进行运算或者访问,结果会不准确!! 数据库当中存取数据会分成整型、长整型、短整型,长整型支持的数字长度是比JS的安全数大的,当服务器返回给客户端一个长整型的数字,如果超出最大安全数值就会出现问题。

 解决方案

  • 服务器端给客户端返回大数,按照字符串格式返回!
  • 客户端把其变换成 Bigint
  • 最后把运算后的BigInt转换为字符串,再传递给服务器
console.log(BigInt('9007199254740991')   BigInt(12345)); // 9007199254753336n
console.log(9007199254753336n.toString()); // 9007199254753336
// 123n  在数字后面直接加`n`也表示大数BigInt

数据类型检测

  • typeof
  • instanceof
  • constryctor
  • Object.prototype.toString.call
  • Array.isArray
  • isNaN

在日常开发中用到最多的就是typeof检测数据类型,所有的数据类型值,在计算机底层都是按照'64位'的二进制进行存储的!type是按照二进制值进行检测类型的

例如

  • 二进制的前三位是0,认为是对象,然后再去看有没有实现call方法,如果实现了返回'functhon',没有时间,则返回'object'
  • 第一位是1为整数
  • 010浮点数
  • 100字符串
  • 110布尔
  • 000000... null(null为64个0) ==> object [因为typeof的局限性]
  • ......

检测未被申明的变量,值为undefined

console.log(a); // ReferenceError: a is not defined
console.log(typeof a); // undefined

场景1:检测当前值是否是一个对象

const fn = options =>{
   let type = typeof options
   if(options !== null && (type === 'object' || type === 'function')){
    // 这样进来的才能确保是一个对象
   }
}
fn({
  num:10
})

场景2:支持更多的模块导入方案

(function(){
  if(typeof window !== 'undefined') window.utils = utils
  if(typeof module === 'object' && typeof module.exports == 'object') module.exports = utils
})()

数据类型间的相互转换

数据类型间的相互转换主要有隐式数据类型转换和显示数据类型转换两种。 一般用于浏览器中的隐式转换

  • 数学运算
  • isNaN检测
  • == 比较

比如说在数据运算时会进行隐式数据类型转换,10-2的时候实际上默认就调用了Number('2')进行了类型转换之后才进行的减法运算。

比如用isNaN来判断时前值是不是一个有效数字,就相当于调用了下面的方法,先调用Number再执行isNaN。

规则

Number([val])

  • 字符串转换为数字:空字符串变为0,如果出现任何非有效数字字符都是NaN
  • 把布尔值转换成数字:true=>1 false=>0
  • null=>0 undefined=>NaN
  • Symbol无法转换为数字,会报错:Cannot convert a Symbol value to a number
  • BigInt去除'n'(超出安全数字的会按照科学计数法处理)
  • 那对象转换为数字:先调用对象的Symbol.toPrimitive方法,如果不存在这个方法,再调用valueOf获取原始值,如果获取的值不是原始值,在调用toString把其变为字符串,最后自傲把字符串用过Number方法进行转换
let time = new Date()
console.log(Number(time)); // 1662715039452
console.log(time[Symbol.toPrimitive]('number')); // 1662715039452
// 首先检测 Symbol.toPrimitive有没有, 结果:有 而且是一个函数 time[Symbol.toPrimitive]('number')
let arr = [10]
console.log(Number(arr));
/**
 * 首先arr[Symbol.toPrimitive] => undefined
 * 然后arr.valueOf() 数组是没有原始值的 => [10]  任何一个对象都有valueOf
 * 再然后 arr.toString => '10'
 * 最后在把字符串'10'转换为数字 => 10
*/
let num = new Number(10)
console.log(Number(num));
/**
 * 首先num[Symbol.toPrimitive] => undefined
 * 然后num.valueOf() 数组是没有原始值的 => 10
*/

parseInt([val],[radix]) parseFloat([val])

parseInt([val],[radix])是可以传两个值进去的:

  • value必须是字符串,不是字符串会会先隐式转换成字符串,通过String([val]),如果是对象会用上面的三步进行转换
  • radix进制,如果不写或者写0,则默认为10进制,如果字符串是以0x开始的,默认为16进制,有效进制范围2~36之间(如果不在这个区间结果直接是NaN)。从[val]字符串左侧开始第一个字符开始查找,查找出符合[radix]进制的值(遇到不符合的则结束查找,无论后面是否还有有符合的),把找到的内容按照[radix]进制,转化为10进制!!
console.log(parseInt('10103px13',2));  // 10
/**
 * 首先找到符合二进制的数 '1010'
 * 把这个二进制值转换为十进制 '按权展开求和'
 * 1*2^3 0*2^2 1*2^1 0*2^0 => 8 0 2 2 => 10
*/

这里放一道字节面试题

arr会输出什么,为什么?
let arr = [27.2,0,'0013','14px',123]
arr = arr.map(parseInt)

解题步骤

  • arr.map方法:迭代数组中的每一项,并且把每一项进行修改,原始数组不变,以新数组的形式返回。迭代数组中的每一项item为当前值,index为索引。
  • map中应该接受一个函数,现在我们是把parseInt作为这个函数传递进去了,所以每次迭代都会执行parseInt并且将item和index作为参数传递进去
/**
 * parseInt(27.2,0) => 找符合二进制的'27',当做十进制转成十进制=> 27
 * parseInt(0,1) => 超出有效进制范围 => NaN
 * parseInt('0013',2) => 001 当做二进制转化为十进制 => 0 0 1 => 1
 * parseInt('14px',3) => 1 当做三进制转成十进制 => 1
 * parseInt(123,4) => parseInt('123',4) => 123当做四进制转成十进制 1*4^2 2*4^1 3*4^0 => 16 8 4 => 27
*/

所以最终得:arr =  [27, NaN, 1, 1, 27]

:

parseInt('0013',2) => 001 当做二进制转化为十进制 => 0 0 1 => 1
parseInt(0013,2) => 0013 当js中遇到以0开头的数字会默认当做8进制转为10进制然后在进行其他运算 => 当做八进制转为十进制 0*8^3 0*8^2 1*8^1 3*8^0 => 11 => 二进制转十进制 11   2 1=3

把其他类型转换为String

转换规则:

  • ' '出现左右两边,其中一边是字符串,或者是某些对象,会以字符串拼接的规则处理
  • ' '出现在一个值的左边,转换为数字
console.log(10   '10'); // 1010
console.log(10   new Number(10));
// new Number(10)[Symbol.toPrimitive] -> undefined
// new Number(10).valueOf() => 10 
//  10   10 = 20
console.log(10   new Date());
// new Date()[Symbol.toPrimitive]('default') -> 不知道传递什么会传defaulu => 'Tue Sep 13 2022 17:00:40 GMT 0800 (中国标准时间)'
// 最终等于:10'Tue Sep 13 2022 17:00:40 GMT 0800 (中国标准时间)'
console.log(10   [10]);
// [10][Symbol.toPrimitive] -> undefined
// [10].valueOf => '[10]' 
// [10].toString() => '10'
// 最终等于: '1010'
let num = '10'
console.log( num) // 10 转换为数字

把其他类型的值转换成Boolean

Boolean(0) = false 除了0 NaN undefined 空字符串 null 以外都是true

==两个等号比较规则

  • ==相等,两边数据类型不同,首先要转换为相同类型,然后在进行比较
  • 对象==字符串 对象转字符串[Symbol.toPrimitive]->valueOf()->toString()
  • null == nudefined -> true null/undefined和其他任何值都不相等
  • null === undefined -> false
  • 对象==对象 比较的是堆内存地址,地址相同则相等
  • NaN !== NaN
  • 除了以上情况,只要两边类型不一致,剩下的都是转换为数字,然后在进行比较的,'==='绝对相等,如果两边类型不同则直接是false,不会转换数据类型。
NaN == NaN // false NaN永远不可能等于NaN
console.log(Object.is(NaN,NaN)); // true

贴一道面试题 下面输出为什么?

console.log([]==false); // 首先都会转换为数字, 0 == 0 => true
console.log(![]==false); // 先处理![]=>false == false  =>true

Js中的装箱和拆箱

装箱和拆箱都是浏览器进行数据类型隐式转换的过程

let num = 10
console.log(num.toFixed(2)); // 10.00
// num是原始值,不是对象,按常理来讲是不能做'成员访问'的
// 默认会做装箱操作:  new Number(num) 变为非标准铁树对象,这样就可以调用toFixed了
let num = new Number(10)
console.log(num   10); // 20 
// 在操作的过程中浏览器会将num这个非标准特殊对象变为原始值  [Symbol.toPrimitive] -> valueOf -> toString 这个操作叫做拆箱
// 装箱和拆箱都是浏览器进行数据类型隐式转换的过程

到此这篇关于JavaScript数据类型及相互间的转换规则的文章就介绍到这了,更多相关JavaScript数据类型内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

JavaScript数据类型及相互间的转换规则的更多相关文章

  1. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  2. HTML5数字输入仅接受整数的实现代码

    这篇文章主要介绍了HTML5数字输入仅接受整数的实现代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. amaze ui 的使用详细教程

    这篇文章主要介绍了amaze ui 的使用详细教程,本文通过多种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  4. html5简介_动力节点Java学院整理

    这篇文章主要介绍了html5简介,用于指定构建网页的元素,这些元素中的大多数都用于描述网页内容,有兴趣的可以了解一下

  5. ios 8 Homescreen webapp,关闭和打开iPad停止javascript

    我有一个适用于iPad的全屏HTML5网络应用程序,并且刚刚安装了IOS8来试用它,它一切正常,直到你关闭并重新启动iPad.一旦web应用程序重新启动javascript就会停止并加载新页面不会重新启动它.在iPad上的Safari中打开同一页面时,关闭和打开iPad会继续按预期工作.其他人注意到了这个或想出了一个解决方案吗?解决方法这似乎是我在iOS8.1.1更新中解决的.

  6. iOS 6 javascript与object.defineProperty的间歇性问题

    当访问使用较新的Object.defineProperty语法定义属性的对象的属性时,有没有其他人注意到新iOS6javascript引擎中的间歇性错误/问题?https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty我正在看到javascript失败的情况,说

  7. ios – 如何使用JSExport导出内部类的方法

    解决方法似乎没有办法将内部类函数导出到javascript.我将内部类移出并创建了独立的类,它起作用了.

  8. 静音iOS推送通知与React Native应用程序在后台

    我有一个ReactNative应用程序,我试图获得一个发送到JavaScript处理程序的静默iOS推送通知.我看到的行为是AppDelegate中的didReceiveRemoteNotification函数被调用,但是我的JavaScript中的处理程序不会被调用,除非应用程序在前台,或者最近才被关闭.我很困惑的事情显然是应用程序正在被唤醒,并且它的didReceiveRemoteNotifi

  9. ios – 内存泄漏与UIWebView和Javascript

    清楚地包含一个Javascript文件到我的HTML是使UIWebView泄漏内存.当我重复使用相同的UIWebView对象时,或者每当我有内容实例化一个新的漏洞时,会出现泄漏的事实,导致我认为必须有一些JavaScript文件被loadHTMLString处理,导致泄漏.有人知道如何解决这个问题吗?

  10. iOS应用程序的UI自动化测试如何与乐器和Javascript

    从WWDC2010视频会议中了解iOS应用程序的自动化UI测试,但没有实践.从代码项目project,我们可以有一个例子.这个问题在这里听到有涉及这个的人.任何限制?解决方法我建议从AlexWollmer开始使用thisblogpost.他创建了一个非常有用的JavaScript库:tuneup_jswithtest()函数,它允许测试分离和有用的帮助者以及为自动化仪器编写测试的断言.

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部