Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS数据类型转换 #31

Open
conan1992 opened this issue Jun 20, 2020 · 0 comments
Open

JS数据类型转换 #31

conan1992 opened this issue Jun 20, 2020 · 0 comments

Comments

@conan1992
Copy link
Owner

conan1992 commented Jun 20, 2020

1. 类型转换种类

  • 转换成布尔值
  • 转换成数字
  • 转换成字符串

2. 转换

原始值 转换目标 结果
number 布尔值 除了0、-0、NaN都为true
string 布尔值 除了空串都为true
undefined、null 布尔值 false
引用类型 布尔值 True
number 字符串 5=》‘5’
Boolean 字符串 'true'
数组 字符串 [1,2]=》‘1,2’
对象 字符串 ‘[object Object]’
string 数字 ‘1’=》1,‘a’=> NaN
数组 数字 空数组为0,存在一个元素且为数字转数字,其他情况为NaN
null 数字 0
除了数组的引用类型 数字 NaN
Symbol 数字 抛错

注意"Boolean 转字符串"这行结果指的是 true 转字符串的例子
null == 0 => false

var bool = true
    console.log(bool.toString())// "true"

3. == 和 ===

JavaScript 有两种比较方式:严格比较运算符和转换类型比较运算符。对于严格比较运算符(===)来说,仅当两个操作数的类型相同且值相等为 true,而对于被广泛使用的比较运算符(==)来说,会在进行比较之前,将两个操作数转换成相同的类型。对于关系运算符(比如 <=)来说,会先将操作数转为原始值,使它们类型相同,再进行比较运算。

  • 严格比较运算符(===)
    左右两边不仅值要相等,类型也要相等
  • 转换类型比较运算符(==)

比较操作符会为两个不同类型的操作数转换类型,然后进行严格比较。当两个操作数都是对象时,JavaScript会比较其内部引用,当且仅当他们的引用指向内存中的相同对象(区域)时才相等,即他们在栈内存中的引用地址相同。

4. ==类型转换规则

  • 两边的类型是否相同,相同的话就比较值的大小,例如1==2,返回false
  • 判断的是否是null和undefined,是的话就返回true
  • null 和 undefined是相等的
  • 判断的类型是否是String和Number,是的话,把String类型转换成Number,再进行比较
  • 判断其中一方是否是Boolean,是的话就把Boolean转换成Number,再进行比较
  • 如果其中一方为Object,且另一方为String、Number或者Symbol,会将Object转换成字符串,再进行比较
console.log({a: 1} == true);//false
console.log({a: 1} == "[object Object]");//true

5. 对象转原始类型流程

对象转原始类型,会调用内置的[ToPrimitive]函数,对于该函数而言,其逻辑如下:

  • 如果Symbol.toPrimitive()方法,优先调用再返回
  • 调用valueOf(),如果转换为原始类型,则返回
  • 调用toString(),如果转换为原始类型,则返回
  • 如果都没有返回原始类型,会报错
    image
    注:图片截取自MDN
var obj = {
      value: 1,
      toString(){
        return 2
      },
      valueOf(){
        return 3
      },
      [Symbol.toPrimitive](){
        return 4
      }
    }
    console.log( obj + 1)// 5

6 运算符的类型转换

  • -、*、/、%这四种都会把符号两边转成数字来进行运算
  • +由于不仅是数字运算符,还是字符串的连接符,所以分为两种情况:
    • 两端都是数字则进行数字计算(一元正号+b这种情况相当于转换为数字)
    • 有一端是字符串,就会把另一端也转换为字符串进行连接
      注意点:
      (+号对于对象的转换)
  • +b的情况就相当于转为数字
  • +号两边有值则判断两边值的类型,若两边都为数字则进行数字计算,若有一边是字符串,就会把另一边也转换为字符串进行连接
var b = {}
console.log(+b)//NaN
console.log(b + 1)//“[object object]1”
console.log(1 + b)//“1[object object]”
console.log(b + '')//“[object object]”

7. 拓展

  • [] == ![]结果是什么?为什么?
    首先右边![]得到布尔值,由于[]作为一个引用类型转换为布尔值为true, 因此![]为false,进而在转换成数字,变为0。左边空数组转换成数字也为0,所以答案为true
  • 如何让if(a == 1 && a == 2)条件成立?
var a = {
      value: 1,
      toString: function(){
        return this.value++
      }
    }
    if(a == 1 && a == 2){
      console.log(true)
    }
或者
var a = {
      value: 1,
      valueOf: function(){
        return this.value++
      }
    }
    if(a == 1 && a == 2){
      console.log(true)
    }
  • 输出什么?
console.log({} + [])//"[object object]"
console.log([2] - [] + function () {})//"2function(){}" 函数是会转换为源代码字符串的。
  • 让if(a == 1 && a == 2 && a == 3)条件成立的办法
    • 重写Symbol.primitive或者valueOf或者toString
var a = {
    value: 0,
    [Symbol.toPrimitive](hint){
        console.log(hint)
        return ++this.value
    }
}
if(a == 1 && a == 2 && a == 3){
    console.log("in")
}
  • 利用数组转为字符串会隐式调用join()
    对象如果是数组的话,当我们不重写其toString()方法,在转换为字符串类型的时候,默认实现就是将调用join()方法的返回值作为toString()的返回值
let a = [1, 2, 3]
a['join'] = function () {
  return this.shift()
}
if (a == 1 && a == 2 && a == 3) {
  console.log('成立')
}

参考:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant