资讯专栏INFORMATION COLUMN

JavaScript类型:关于类型,有哪些你不知道的细节?

JessYanCoding / 684人阅读

摘要:通过拆箱转换,把对象编程基本类型,再从从基本类型转换成对应的或者。拆箱转换会尝试调用和来获得拆箱后的基本类型。

undefined和null

  Undefined类型表示未定义,它的类型只有一个值为undefined。任何变量在赋值前都是undefined类型,值为undefined。但是JS中undefined是一个变量,并非是一个关键字,为了避免无意中的篡改,使用void 0来获取undefined值。

  undefined和null有一定的表意差别,null表示“定义了但是为空”,它只一个值为null,并且是JS关键字,可以放心使用。

Number

  非整数的Number类型无法使用 == 或 === 来比较,有一段著名的代码

console.log(0.1 + 0.2 == 0.3);

  输出结果是false,说明两边不等,这是浮点运算的特点,浮点数运算的精度问题导致等式左右并不是严格相等,而是相差了个微小的值。

  正确的比较方法是使用JS提供的最小精度值:

console.log(Math.abs(0.1 + 0.2 -0.3) <= Number.EPSILON);

  检查等式左右两边差的绝对值是否小于最小精度值,才是正确的比较浮点数的方法。

类型转换

  因为 JS 是弱类型语言,所以类型转换发生非常频繁,大部分我们熟悉的运算都会先进行类型转换。大部分类型转换符合人类的直觉,但是如果我们不去理解类型转换的严格定义,很容易造成一些代码中的判断失误。其中最为臭名昭著的是 JS 中的“ == ”运算,因为试图实现跨类型的比较,它的规则太过复杂。很多实践中推荐禁止使用“ ==”,而要求程序员进行显式地类型转换后,用 === 比较。

  parseInt 和 parseFloat 是很常用的类型转换的方法。在不传入第二个参数的情况下,parseInt 只支持 16 进制前缀“0x”,而且会忽略非数字字符,也不支持科学计数法。在一些古老的浏览器环境中,parseInt 还支持 0 开头的数字作为 8 进制前缀,这是很多错误的来源。所以在任何环境下,都建议传入 parseInt 的第二个参数,而 parseFloat 则直接把原字符串作为十进制来解析,它不会引入任何的其他进制。

  多数情况下,Number 是比 parseInt 和 parseFloat 更好的选择。

装箱转换

  每一种基本类型 Number、String、Boolean、Symbol 在对象中都有对应的类,所谓装箱转换,正是把基本类型转换为对应的对象,它是类型转换中一种相当重要的种类。全局的 Symbol 函数无法使用 new 来调用,但我们仍可以利用装箱机制来得到一个 Symbol 对象,我们可以利用一个函数的 call 方法来强迫产生装箱。我们定义一个函数,函数里面只有 return this,然后我们调用函数的 call 方法到一个 Symbol 类型的值上,这样就会产生一个 symbolObject。

  我们可以用 console.log 看一下这个东西的 type of,它的值是 object,我们使用 symbolObject instanceof 可以看到,它是 Symbol 这个类的实例,我们找它的 constructor 也是等于 Symbol 的,所以我们无论哪个角度看,它都是 Symbol 装箱过的对象:

    
var symbolObject = (function(){ 
    return this; 
}).call(Symbol("a"));

console.log(typeof symbolObject);         //object
console.log(symbolObject instanceof Symbol);     //true
console.log(symbolObject.constructor == Symbol);    //true

  装箱机制会频繁产生临时对象,在一些对性能要求较高的场景下,我们应该尽量避免对基本类型做装箱转换。

  使用内置的Object函数,可以在JS代码中显式的调用装箱能力。

var symbolObject = Object((Symbol("a"));

console.log(typeof symbolObject);         //object
console.log(symbolObject instanceof Symbol);     //true
console.log(symbolObject.constructor == Symbol);     //true

  每一类装箱对象皆有私有的Class属性,这些属性可以用Object.protoype.toString获取:

var symbolObject = Object((Symbol("a"));
console.log(Object.prototype.toString.call(symbolObject)); //[object Symbol]

  JS中,没有方法可以更改私有的Class属性,因此Object.prototype.toString是可以准确识别对象对应的基本类型的方法,它比instanceof更加准确。

  但需要注意的是,call 本身会产生装箱操作,所以需要配合typeof来区分基本类型还是对象类型。

拆箱转换

  JS标准中,规定了ToPrimitive函数,它是对象类型到基本类型的转换。(即拆线转换)

  对象到String和Number的转换都遵循“先拆箱再转换”的规则。通过拆箱转换,把对象编程基本类型,再从从基本类型转换成对应的String或者Number。

  拆箱转换会尝试调用valueOf和toString来获得拆箱后的基本类型。如果valueOf和toString都不存在。或者没有返回基本类型,则会产生类型错误的提示TypeError。

var o = {
    valueOf : () => {console.log("valueOf"); return {}},
    toString : () => {console.log("toString"); return {}}
}
    
o * 2
// valueOf
// toString
// TypeError

  我们定义了一个对象 o,o 有 valueOf 和 toString 两个方法,这两个方法都返回一个对象,然后我们进行 o * 2 这个运算的时候,你会看见先执行了 valueOf,接下来是 toString,最后抛出了一个 TypeError,这就说明了这个拆箱转换失败了。

  到 String 的拆箱转换会优先调用 toString。我们把刚才的运算从 o*2 换成 o + “”,那么你会看到调用顺序就变了。

var o = {
    valueOf : () => {console.log("valueOf"); return {}},
    toString : () => {console.log("toString"); return {}}
}
 o + ""
// toString
// valueOf
// TypeError

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102397.html

相关文章

  • 重学前端学习笔记(六)--JavaScript类型哪些你不知道细节

    摘要:的码点被称为基本字符区域。关于的介绍,我准备用文档阮一峰来做一些介绍,具体的可以参考文档引入的原因的对象属性名都是字符串,这容易造成属性名的冲突。其他的一些属性可以去看文档阮一峰注意函数前不能使用命令,否则会报错。 笔记说明 重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些要点笔记以及感悟,完...

    Lsnsh 评论0 收藏0
  • 重学前端学习笔记(六)--JavaScript类型哪些你不知道细节

    摘要:的码点被称为基本字符区域。关于的介绍,我准备用文档阮一峰来做一些介绍,具体的可以参考文档引入的原因的对象属性名都是字符串,这容易造成属性名的冲突。其他的一些属性可以去看文档阮一峰注意函数前不能使用命令,否则会报错。 笔记说明 重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些要点笔记以及感悟,完...

    joyvw 评论0 收藏0
  • 重学前端学习笔记(六)--JavaScript类型哪些你不知道细节

    摘要:的码点被称为基本字符区域。关于的介绍,我准备用文档阮一峰来做一些介绍,具体的可以参考文档引入的原因的对象属性名都是字符串,这容易造成属性名的冲突。其他的一些属性可以去看文档阮一峰注意函数前不能使用命令,否则会报错。 笔记说明 重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系,笔者主要整理学习过程的一些要点笔记以及感悟,完...

    zlyBear 评论0 收藏0
  • 前端增长-你不知道那些细节

    摘要:前端增长重新定义大前端精心打造全新课程,欢迎吐槽反馈宝贵意见在线课程前端增长你不知道的那些细节附赠常见核心前端面试问题与详细解答官方博客前端学堂课件脑图下载课程介绍前端知识点很多,很细碎。 showImg(https://segmentfault.com/img/bVbu250?w=500&h=497);前端增长-重新定义大前端 精心打造全新课程,欢迎吐槽!反馈宝贵意见! 在线课程:前...

    asce1885 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<