代码基本功测试

js的数据类型

前言

作为JavaScript的入门级知识点JS数据类型在整个JavaScript的学习过程中其实尤为重要

数据类型概念

数据类型大致分为两类来进行存储

  1. 基础类型存储在栈内存中。被引用或拷贝时,会创建一个完全相等的变量。基础数据类型有undefinednullBooleanStringNumberSymbolBigInt
  2. 引用类型存储在堆内存中。存储的是地址,多个引用指向同一个地址,这里会涉及一个“共享”的概念。引用数据类型有ArrayRegExpDateMathFunction

下面用几个例子助于理解

let a={
    name:'xlz',
    age:18
}
let b=a;
console.log(a.name);//第一个console 输出xlz
b.name='son';
console.log(a.name);//第二个console 输出son
console.log(b.name);//第三个console 输出son
复制代码

这里第一个输出xlz大家应该都可以理解,那么第二个第三个输出son原因就是a是一个对象存储在堆内存。a变量存储的是堆内存的地址,b=a是把a的内存地址引用过来,ab共享一个地址,所以b.name='son'修改的是这个地址的对象name属性因此输出都是son

数据类型检测

第一种判断方法:typeof 运算符返回一个字符串,表示操作数的类型。

typeof 1//number
typeof '1'//string
typeof undefined//undefined
typeof true//boolean
typeof Symbol()//symbol
typeof null//Object
typeof []//object
typeof {}//object
typeof console//object
typeof console.log//function
复制代码

typeof 只能检测基本数据类型 引用类型只能检测一个function其余的都是object

在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 "object"

第二种判断方法:instanceof

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

let Car=function(){}
let benz=new Car();
benz instanceof Car//true

let car=new String('Mercedes Benz')
car instanceof String//true

let str='Covid'
str instanceof String//false
复制代码

instanceof实现原理如下

function myInstanceof(left,right){
    //这里先用typeof来判断基本数据类型,如果是,直接返回false
    if(typeof left!=='object'||left===null)return false
    //getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
    let proto=Object.getProtypeOf(left);
    //循环往下寻找,直到找到相同的原型对象
    while(true){
        if(proto===null)return false
        //找到相同原型对象,返回true
        if(proto===right.prototype)return true;
        proto=Object.getProtypeOf(proto)
    }
}
复制代码

可以再控制台验证一下是否ok

两种数据类型的差异

  1. instanceof可以准确的判断复杂引用类型,但是不能正确判断基本数据类型。
  2. typeof也存在弊端,它虽然可以判断基本数据类型(null除外)但是引用数据类型中,除了function类型以外,其他的也无法判断

第三种判断方法:Object.prototype.toString

Object.prototype.toString({})//'[object Object]'
Object.prototype.toString.call({})//同上结果'[object Object]'
Object.prototype.toString.call(1)//'[object Number]'
Object.prototype.toString.call('1')//'[object String]'
Object.prototype.toString.call(true)//'[object Boolean]'
Object.prototype.toString.call(function(){})//'[object Function]'
Object.prototype.toString.call(null)//'[object Null]'
Object.prototype.toString.call(undefined)//'[object Undefined]'
Object.prototype.toString.call(/123/g)//'[object RegExp]'
Object.prototype.toString.call(new Date())//'[object Date]'
Object.prototype.toString.call([])//'[object Array]'
Object.prototype.toString.call(document)//'[object HTMLDocument]'
Object.prototype.toString.call(window)//'[object Window]'
复制代码

这种方法可以检测基本数据类型以及引用类型甚至还可以区分window、document但是要注意的是Object.prototype.toString返回的是[object Xxx]类型第一个首字母是大写开头的

结合以上所学实现一个全局类型检测类型的方法

function getType(obj){
    let type=typeof obj;
    //先进行typeof判断,如果是基础数据类型,直接返回
    if(type!=='object'){
        return type
    }
    //对于typeof返回结果是object,在进行如下的判断,正则返回结果
    return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/,'$1')
}
//代码验证
getType([])//Array toString返回
getType('123')//string typeof返回
getType(window)//Window toString返回
getType(null)//Null toString返回
getType(undefined)//undefined typeof返回
getType(function(){})//function typeof返回
getType(/123/g)//RegExp toString返回
复制代码

数据类型转换

强制类型转换有Number()、parseInt()、parseFloat()、toString()、String()、Boolean()

Number()方法的强制转换规则:

  1. 布尔值 true和false 分别被转换为1和0
  2. 数字 返回自身
  3. null 返回0
  4. undefined 返回NaN
  5. 字符串:如果字符串只包含数字,则将其转换为十进制、如果字符串中包含有效的浮点格式,将其转换为浮点数值、如果是空字符串转换为0、如果不是以上格式字符串,均返回NaN
  6. SYmbol 抛出错误
  7. 对象,并且部署了[Symbol.toPrimitive] 那么调用此方法,否则调用对象的valueOf()方法
Number(true)//1
Number(false)//0
Number('0111')//111
Number(null)//0
Number('')//0
Number('1a')//NaN
Number(-0X11)//-17
Number(0X11)//17
复制代码

Boolean()方法的转换规则: 除了undefined、null、false、’‘、0、(包括+0,-0)、NaN转换出来是false其余都是true

parseInt()、parseFloat()、toString()、String()可以参照上面的方式自打印结果总结一下

在开发中头疼的不是强制类型转换而是隐式类型转换,隐式类型转换包括:

  1. 逻辑运算符 && || !
  2. 运算符+ - * /
  3. 关系操作符 > < <= >=
  4. 相等运算符 ==
  5. if/while条件

这次分析开发中比较常用的==与+的隐式规则

==隐式类型转换规则

  1. 如果类型相通无需进行转换
  2. 如果其中一个操作符是null或者是undefined那么另一个操作符必须为null或undefined才会返回true,否则都是false。
  3. 如果其中一个是Symbol类型那么返回false
  4. 两个操作符如果都为StringNumber类型那么就会将字符串转换为number
  5. 如果一个操作符是boolean那么转换成number
  6. 如果一个操作符值为Object且另一方为string、number或者symbol就会把object转为原始类型在进行判断
null==undefined//true 规则2
null==0 //false 规则2
''==null //false 规则2
''==0 //true 规则4 字符串隐式转换numbe在对比
'123'==123 //true 规则4 字符串隐式转换numbe在对比
0==false //true规则5 
1==true//true规则5 

var a={
    value:0,
    valueOf:function(){
        this.value++;
        return this.value
    }
}
console.log(a==1&&a==2&&a==3);//true 规则6 object隐式转换
//之前的面试题如果让 a==1&&a==2&&a==3 等式成立
//执行a==1会调用valueOf一次value++一次a==2也是调用valueOf value++一次
//执行过3遍之后,再重新执行a==3或者之前的数字就是false
复制代码

'+'的隐式类型转换规则

  1. '+'号操作符,不仅可以用作数字相加,还可以用字符串拼接 如果两个都是数字就进行加法运算、如果两个有一个是字符串那么就会是字符串拼接
  2. 如果其中有一个是字符串,另一个是undefined、null或布尔型则调用toStriing()方法进行字符串拼接。如果是纯对象、数组、正则等,则默认调用对象的转换方法会存在优先级,然后再进行拼接。
  3. 如果其中有一个是数字,另一个是undefined、null、布尔型和数字,则会转换成数字进行加法运算,对象的情况还是参考上一条规则
1+2 //3 常规情况
'1'+'2' //'12' 常规情况
//特殊情况
'1'+undefined //‘1undefined’ 规则2 undefined转换字符串
'1'+null //‘1null’ 规则2 null转换字符串
'1'+true //‘1true’ 规则2 true转换字符串
'1'+1n //‘11’ 比较特殊字符串和BigInt,BigInt转换为字符串

1+undefined //NaN 规则3 undefined转换数字相加NaN
1+null //‘1’ 规则3 null转换0
1+true //‘2’ 规则1 true转换1
1+1n //错误 不能把BigInt和Number类型混合相加1’+3 // '13'规则1 字符串拼接
复制代码

object的转换规则

  1. 如果部署了Symbol.toPrimitive方法优先调用再返回
  2. 调用valueOf,如果转换为基础类型则返回
  3. 调用toString(),如果转换为基础类型则返回
  4. 如果都没有返回基础类型会报错
var obj={
    value:1,
    valueOf(){
        return 2
    },
    toString(){
        return '3'
    },
    [Symbol.toPrimitive](){
        return 4
    }
}
console.log(obj+1)//输出5
//因为有Symbol.toPrimitive,就优先执行这个;如果Symbol.toPrimitive这段代码删掉,则执行valueOf打印为3,如果valueOf也去掉,则调用toStrig返回‘31’(字符串拼接)
复制代码

本文使用 文章同步助手 同步

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

推荐阅读更多精彩内容