数据类型转换1

2020-12-07  本文已影响0人  撑船的摆渡人

数据转换两种方式,隐式转换和显式转换。

字符串拼接
console.log(10 + '10')
// '1010'
数学运算(+ - * /...)
console.log(+'10')
// 10
console.log(10 - '10')
// 0
==比较
console.log(10=='10')
// true
console.log(10==='10')
// false
显示转换
Number('10')
// 10
String(10)
// '10'

对象转换为数字/字符串经历了哪些步骤(底层机制)

  1. 首先检测对象的 Symbol.toPrimitive 这个属性,获取其原始值
  2. 如果没有这个属性,则继续调用它的 valueOf ,也是获取原始值
  3. 如果值不是原始值,则继续调用 toString 转换为字符串
  4. 再把字符串转使用 Number 换为数字
let obj = {name:10}
obj - 10 = NaN
1. obj[Symbol.toPrimitive] 
// undefined
2. obj.valueOf()
// {0: 10}
3. obj.toString()
// '[object Object]'
4. Number('[object Object]')
// NaN
5. NaN-10
// NaN

那为什么 new Number(10) 也是对象,结果却不一样呢?我们来看一下

typeof new Number(10)  
// 'object' 
let n = new Number(10)
n - 5 = 5
1. n[Symbol.toPrimitive]
// undefined
2. n.valueOf()
// 10
// 10 - 5 =5

让我们来练习一下,改造一下第一个对象

let obj = {
  name: 10,
  [Symbol.toPrimitive]() {
    return 10
  }
}
console.log(obj - 10)
// 0

看一道阿里的面试题,是不是觉得就超级简单了,当初这道题的正确率可是很低的,通过率可能1%都不到

var a = ?;
if (a == 1 && a == 2 && a == 3) {
    console.log('OK');
}

知道了对象转数字的步骤我们就可以来做了,这边提供两类解题思路,第一类隐式进行数据类型转换来进行处理,就是上面我们看到对象转换数字的步骤,我们至少能用三种方法;如果算上数组转数字的话也至少能再用三种方法;第二类,就是我们的数据劫持,也是起码两种方法。我们来试一试吧


第一种方法,给对象添加 Symbol.toPrimitive
var a = {
  n: 1,
  [Symbol.toPrimitive]() {
    return this.n++
  }
};
if (a == 1 && a == 2 && a == 3) {
    console.log('OK');
}
第二种方法,给对象添加 valueOf
var a = {
  n: 1,
  valueOf() {
    return this.n++
  }
};
if (a == 1 && a == 2 && a == 3) {
    console.log('OK');
}
第三种方法,给对象添加 toString
var a = {
  n: 1,
  toString() {
    return this.n++
  }
};
if (a == 1 && a == 2 && a == 3) {
    console.log('OK');
}
数组的第一种方法...
var a = [1,2,3]
a.toString = a.shift
if (a == 1 && a == 2 && a == 3) {
    console.log('OK');
}
第四种方法,使用ES5的 Object.defineProperty
var a = {
  n: 1,
  toString() {
    return this.n++
  }
};
if (a == 1 && a == 2 && a == 3) {
    console.log('OK');
}
第五种方法,使用ES6的 proxy
var a = {
  n: 1,
  toString() {
    return this.n++
  }
};
if (a == 1 && a == 2 && a == 3) {
    console.log('OK');
}

补充一个知识点

Symbol.toPrimitive

在 Symbol.toPrimitive 属性(用作函数值)的帮助下,一个对象可被转换为原始值。该函数被调用时,会被传递一个字符串参数 hint ,表示要转换到的原始值的预期类型。 hint 参数的取值是 "number"、"string" 和 "default" 中的任意一个。

// 一个没有提供 Symbol.toPrimitive 属性的对象,参与运算时的输出结果
var obj1 = {};
console.log(+obj1);     // NaN
console.log(`${obj1}`); // "[object Object]"
console.log(obj1 + ""); // "[object Object]"

// 接下面声明一个对象,手动赋予了 Symbol.toPrimitive 属性,再来查看输出结果
var obj2 = {
  [Symbol.toPrimitive](hint) {
    if (hint == "number") {
      return 10;
    }
    if (hint == "string") {
      return "hello";
    }
    return true;
  }
};
console.log(+obj2);     // 10      -- hint 参数值是 "number"
console.log(`${obj2}`); // "hello" -- hint 参数值是 "string"
console.log(obj2 + ""); // "true"  -- hint 参数值是 "default"
上一篇 下一篇

猜你喜欢

热点阅读