JavaScript面试考点之数据类型及类型转换

1、JavaScript中的数据类型

在JavaScript中,我们把数据可以分为基本类型和引用类型。

1)基本数据类型NumberStringBooleanUndefinednullsymbol(es6新增,表示独一无二的值),BigInt(es10新增)。

2)引用数据类型Object。Object包括函数对象-Function、普通对象-Object、数组对象-Array、正则对象-RegExp、日期对象-Date、Math数学函数对象等。

注意:a、在数值类型中,存在一种特殊数值NaN,意思为“不是数值”(可以使其他任何类型,所以NaN!=NaN。),用于表示返回数值的操作失败了(不是抛出错误)。isNaN用来检测这个值是否为有效数字,不是有效数字则返回true,是有效数字返回false。

b、Undefined类型只有一个值就是特殊值undefined。当声明了变量但没有初始化时,就相当于给变量赋予了undefined值。

c、字符串一旦创建,值就不能改变了。如 let lang = "java"; lang = lang+"script" 。lang是先销毁再创建。

d、Null类型同样只有一个值,即特殊值null,表示一个空对象指针。这也是给typeof传一个 null 会返回 "object" 的原因。(let car = null; console.log(typeof car);  // "object")只要变量要保存对象,如果暂时没有哪个对象可保存,就可以用null来填充。undefined值由null值派生而来。(console.log(null == undefined); // true)

e、基本数据类型和引用数据类型存储在内存中的位置不同。基本数据类型存储在栈中,存放的是对应的值;引用数据类型存储在堆中,在栈中存放的是指向堆内存的地址。

2、数据类型检测

1)typeof 检测数据类型的逻辑运算符

typeof 操作符返回一个字符串,表示未经计算的操作数的类型。直接在计算机底层基于数据类型的值(二进制)进行检测。

typeof 对于原始类型除了 null 都可以显示正确的类型。

typeof对于对象除了函数都会显示object。所以说typeof并不能准确判断变量到底是什么类型,所以想判断一个对象的正确类型,这时候可以考虑使用instanceof。

2)instanceof 检测是否为某个类的实例

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

instanceof的实现原理:顺着原型链去找,直到找到相同的原型对象,返回true,否则为false。

3)constructor 检测构造函数

如果我创建一个对象,更改它的原型,constructor就会变得不可靠了

4)Object.prototype.toString.call 检测数据类型

如果需要通用检测数据类型,可以采用Object.prototype.toString,调用该方法,统一返回格式“[object Xxx]”的字符串,其中Xxx就是对象的类型。

对于Object对象,直接调用toString()就能返回[object Object];而对于其他对象,只要把Object.prototype.toString执行,让它里面的this变为要检测的值,即需要通过call来调用,才能返回正确的类型信息。

总结:

typeof会返回一个变量的基本类型;instanceof返回的是一个布尔值;constructor返回的是一个布尔值

instanceof可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型;我们可以肆意的修改原型的指向,所以检测不准确。

而typeof 也存在弊端,它虽然可以判断基础数据类型(null 除外,因为对象存储在计算机中,都是以000开始的二进制存储,null也是,所以检测出来的结果是对象),但是引用数据类型中,除了function 类型以外,其他的也无法判断(“object”)。

实现:

传递的值是null或者undefined,就返回对应的字符串。基本数据类型都采用typeof检测。其他使用Object.prototype.toString。

3、JavaScript中的类型转换机制

我们在声明的时候只有一种数据类型,只有到运行期间才会确定当前类型。虽然变量的数据类型是不确定的,但是各种运算符对数据类型是有要求的,如果运算子的类型与预期不符合,就会触发类型转换机制。常见的类型转换有:强制转换(显示转换)、自动转换(隐式转换)

1)常见的显示转换方法有:Number()、parseInt()、String()、Boolean()

Number() 函数是将任意类型的值转化为数值。转化规则如下:

parseInt() 函数逐个解析字符,遇到不能转换的字符就停下来。

parseInt() 方法首先查看位置 0 处的字符,判断它是否是个有效数字;如果不是,该方法将返回 NaN,不再继续执行其他操作。但如果该字符是有效数字,该方法将查看位置 1 处的字符,进行同样的测试。这一过程将持续到发现非有效数字的字符为止,此时 parseInt() 将把该字符之前的字符串转换成数字。例如,如果要把字符串 "12345red" 转换成整数,那么 parseInt() 将返回 12345,因为当它检查到字符 r 时,就会停止检测过程。

字符串中包含的数字字面量会被正确转换为数字,比如 "0xA" 会被正确转换为数字 10。不过,字符串 "22.5" 将被转换成 22,因为对于整数来说,小数点是无效字符。

parseInt() 方法还有基模式,可以把二进制、八进制、十六进制或其他任何进制的字符串转换成整数。基是由 parseInt() 方法的第二个参数指定的,所以要解析十六进制的值,需如下调用 parseInt() 方法:var iNum1 = parseInt("AF", 16);//返回 175。

parseInt(string,radix)

在没有指定radix或者radix为0的情况下,parseInt会按十进制进行转换。然而,这在某些情况下有点特殊:

如果string的值以“0x”开头,parseInt会按十六进制进行转换;

如果string的值以“0”开头,parseInt会按八进制进行转换。

parseInt("0x10"); //字符串以0x开头则将之后的数字按16进制解读,16进制的10也就是十进制的16, 因此输出为16

parseInt("0xa"); //10,要注意16进制包括0~9,a~f (也就是10~15),超出该范围的字符不被解读。

parseInt("0xg"); //NAN

这三个例子分别等价于 parseInt("0x10",16)  parseInt("0xa",16)  parseInt("0xg",16)/

parseInt()的参数是一个字符串类型;parseInt 会先调用 toString 方法。对于小于 1e-6 的数值来说,ToString 时会自动转换为科学计数法。 数值0.0000000007先会被转换成字符串“7e-10”(科学计数法); 即执行了parseInt("7e-10"); 字符e不是十进制类型之后一起被截掉。

但是还存在下面的情况:当大于 1e-6 的数值不会转换为科学计数法。

parseFloat() 方法

对于这个方法来说,第一个出现的小数点是有效字符。如果有两个小数点,第二个小数点将被看作无效的。parseFloat() 会把这个小数点之前的字符转换成数字。这意味着字符串 "11.22.33" 将被解析成 11.22。

使用 parseFloat() 方法的另一不同之处在于,字符串必须以十进制形式表示浮点数,而不是用八进制或十六进制。该方法会忽略前导 0,所以八进制数 0102 将被解析为 102。对于十六进制数 0xA,该方法将返回 NaN,因为在浮点数中,x 不是有效字符。(注释:经测试,具体的浏览器实现会返回 0,而不是 NaN。)

String() 函数可以将任意类型的值转化成字符串。转化规则如下:

Boolean() 函数可以将任意类型的值转为布尔值。在条件判断时,除了undefined,null,false,NaN,'',0,-0,其他所有值都转为true,包括所有对象。

2)常见的隐式转化场景

a、比较运算(==、!=、>、<)、if、while需要布尔值地方

b、算术运算(+、-、*、/、%)

运算中其中一方为字符串,那么就会把另一方也转换为字符串;如果一方不是字符串或者数字,那么会将它转换为数字或者字符串。

那么对于除了加法的运算符来说,只要其中一方是数字,那么另一方就会被转为数字。

自动转换为布尔值:在需要布尔值的地方,就会将非布尔值的参数自动转为布尔值,系统内部会调用Boolean函数。除了undefined、null、false、+0、-0、NaN、"" 会被转化成false,其他都换被转化成true。

自动转换成字符串:遇到预期为字符串的地方,就会将非字符串的值自动转为字符串。具体规则是先将复合类型的值转为原始类型的值,再将原始类型的值转为字符串。常发生在+运算中,一旦存在字符串,则会进行字符串拼接操作。

自动转换成数值:除了+有可能把运算子转为字符串,其他运算符都会把运算子自动转成数值。null转为数值时,值为0 。undefined转为数值时,值为NaN。

4、== 和 ===区别

等于操作符用两个等于号( == )表示,如果操作数相等,则会返回 true。

由于JavaScript中存在隐式转换,等于操作符在比较中先进行类型转换,再确定操作数是否相等。规则如下:

如果两个都为简单类型,字符串和布尔值都会转换成数值,再比较是否相等;简单类型与引用类型比较,对象转化成其原始类型的值,再比较是否相等;两个都为引用类型,则比较它们是否指向同一个对象;null 和 undefined 相等;存在 NaN 则返回 false;

全等操作符用 3 个等于号( === )表示,只有两个操作数在不转换的前提下相等才返回 true。即类型相同,值也需相同。null 和 undefined 不相等。

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

推荐阅读更多精彩内容