angular8类型转换 string转number_菜鸟前端的咸鱼之旅-第八天:类型转换-装箱,拆箱...

a1161b75b83ca9cf71174126ea970fe2.png
需要的前置知识:四则运算相关,原始类型和对象类型相关。

js的数据类型分为两种,原始类型和对象类型。

原始类型存储的都是值,是没有函数可以调用的,比如 undefined.toString() 会抛出错误。

但为什么 '1'.toString() 是可以使用的。

其实是 . 运算符提供了装箱操作,它会根据基础类型构造一个临时对象,使得我们能在基础类型上调用对应对象的方法。在该临时对象调用函数返回函数操作结果后,将该对象丢弃。

装箱转换

每一种基本类型 Number、String、Boolean、Symbol 在对象中都有对应的类,所谓装箱转换,正是把基本类型转换为对应的对象,它是类型转换中一种相当重要的种类。

全局的 Symbol 函数无法使用 new 来调用,但我们仍可以利用装箱机制来得到一个 Symbol 对象,我们可以利用一个函数的 call 方法来强迫产生装箱。

    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 函数,也可以显式调用装箱能力。

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

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

每一个原始类型装箱对象 console.dir 的时候,会发现有个 [[PrimitiveValue]] 标记,他会显示该对象内部指向的原始值。

原始类型在使用方法时会进行装箱转换,同样,对象在获取原始值时也会进行拆箱转换。

拆箱转换

js 是弱类型语言,所以在进行值加减乘除的操作的时候,会进行隐式的转换,然后进行运算。

类型转换中涉及到三种方法 toNumber, toString 和 toPrimitive 。

这里我们只说 toPrimitive ,也就是隐式转换里对象类型到原始类型的转换(即 拆箱转换 )。

ToPrimitive(input [, PreferredType])

1.如果没有传入PreferredType参数,则让hint的值为'default'
2.否则,如果PreferredType值为String,则让hint的值为'string'
3.否则,如果PreferredType值为Number,则让hint的值为'number'
4.如果input对象有@@toPrimitive方法,则让exoticToPrim的值为这个方法,否则让exoticToPrim的值为undefined
5.如果exoticToPrim的值不为undefined,则
	a.让result的值为调用exoticToPrim后得到的值
	b.如果result是原值,则返回
	c.抛出TypeError错误
6.否则,如果hint的值为'default',则把hint的值重新赋为'number'
7.返回 OrdinaryToPrimitive(input,hint)

OrdinaryToPrimitive(input,hint)

1.如果hint的值为'string',则
	a.调用input对象的toString()方法,如果值是原值则返回
	b.否则,调用input对象的valueOf()方法,如果值是原值则返回
	c.否则,抛出TypeError错误
2.如果hint的值为'number',则
	a.调用input对象的valueOf()方法,如果值是原值则返回
	b.否则,调用input对象的toString()方法,如果值是原值则返回
	c.否则,抛出TypeError错误

上面一堆 ES 的文档说明可能看起来有点懵,不要慌,先来举几个栗子。

在对象拆箱转换的时候会调用 [@@toPrimitive]() 方法,该方法有个 PreferredType 参数,参数为 "string" 或 "number",如果不传,默认为 "default"。

PreferredType 的值会决定 OrdinaryToPrimitive 方法的 hint 参数。

如果 hint 是 "number",[@@toPrimitive]() 会首先尝试 valueOf,若值不是原始值再尝试 toString。如果 toString 也拿不到原始值,则抛出一个 TypeError。

对应 例子1 ,可以将 例子1 中的 valueOf 或者 toString 的 return 值改为原始值再试一下。
    // 栗子1

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

    o * 2
    // valueOf
    // toString
    // Uncaught TypeError: Cannot convert object to primitive value

   // 这个先调用 valueOf , 然后调 toString , 然后报错

如果 hint 是 "string" 或 "default",[@@toPrimitive]() 将会调用 toString。如果 toString 原始值不存在,则调用 valueOf。如果 valueOf 也不存在,则抛出一个 TypeError。(例子2)

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

    o + ""
    // toString
    // valueOf
    // Uncaught TypeError: Cannot convert object to primitive value

   // 这个先调用 toString, 然后调 valueOf, 然后报错

当在希望是字符串操作,也即发生对象到字符串的转换时,传入内部函数 ToPrimitive 的参数值即为 string,当在希望是数值操作,传入内部函数 ToPrimitive 的参数值即为 number,当在一些不确定需要将对象转换成什么基础类型的场景下,传入内部函数 ToPrimitive 的参数值即为 default。(例子3)

     // 栗子3
     const b = {
        [Symbol.toPrimitive](hint) {
          console.log(`hint: ${hint}`)
          return {}
        },
        toString() {
          console.log('toString')
          return 1
        },
        valueOf() {
          console.log('valueOf')
          return 2
        }
      }

      alert(b) // hint: string
      b + '' // hint: default
      b + 500 // hint: default
      ;+b // hint: number
      b * 1 // hint: number

在 ES6 之后,还允许对象通过显式指定 @@toPrimitive Symbol 来覆盖原有的行为。

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

    o[Symbol.toPrimitive] = () => {console.log("toPrimitive"); return "hello"}


    console.log(o + "")
    // toPrimitive
    // hello
// 来几个测试题
var o = { [Symbol.toStringTag]: 'MyObject' }
console.log(o + '');   // [object MyObject]
// + '' hint 为 string  调用 toString 方法, [Symbol.toStringTag] 改变了 [Object Object]

console.log( o * 2 )   // NaN
//  hint 为 number, 调用 valueOf 方法, 返回对象本身, 再调用 toString方法. 返回字符串'[object MyObject ]'
// '[object MyObject ]' 转 Number 为 NaN, NaN * 2  还是 NaN

[] + []
// hint 为 number,所以先调用valueOf(),结果还是[ ],不是原始值,所以继续调用toString(),结果是“”原始值,将“”回。
// 加号两边结果都是String类型,所以进行字符串拼接,结果是“”。

[] + {}
//  ??  可以自己试下,结果是不是符合你的预期。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值