记癌丝-类型转换

记癌丝很灵活,类型转换立大功。

类型转换就是从一种类型转换为另一种类型。这里不想说关于是显式还是隐式的,这全都是相对而言的,你懂对你来说就全是显式。

== 和 === 的区别

==允许在相等比较中进行强制类型转换

===不允许

关于==的各种类型转换我拒绝回答。

ToPrimitive是什么

Symbol.toPrimitive 是内置的 symbol 属性,其指定了一种接受首选类型并返回对象原始值的表示的方法。它被所有的强类型转换制算法优先调用。

js 复制代码
const isBasicType = (val = "") => {
  const t = Object.prototype.toString.call(val);
  if (
    t == "[object String]" ||
    t == "[object Boolean]" ||
    t == "[object Number]" ||
    t == "[object Null]" ||
    t == "[object Undefined]" ||
    t == "[object Symbol]"
  ) {
    return val;
  }
  return;
};

const user = {
  [Symbol.toPrimitive](hint) {
    console.log(hint);
    // 假设这个Symbol.toPrimitive不存在就按照下面的样子转换
    if (hint === "number" || hint === "default") {
      return isBasicType(this.valueOf()) || this.toString();
    }

    if (hint === "string") {
      return isBasicType(this.toString()) || this.valueOf();
    }
  },
  toString() {
    // console.log('toString');
    return "toString";
  },
  valueOf() {
    return 999;
    // console.log('valueOf');
    return "valueOf";
  },
};

console.log("// toPrimitive(number) valueOf -> toString");
console.log("Number(user):", Number(user));
console.log("user - 1:", user - 1);
console.log("user > 1:", user > 1);
console.log("user > 'a':", user > "a");
console.log("user * 2:", user * 2);

console.log("// toPrimitive(default) valueOf -> toString");
console.log("user +1:", user + 1);

console.log("// toPrimitive(string) toString -> valueOf");
console.log("String(user):", String(user));

console.log("// 直接调用toString");
console.log(user.toString());


// toPrimitive(number) valueOf -> toString
number
Number(user): 999
number
user - 1: 998
number
user > 1: true
number
user > 'a': false
number
user * 2: 1998

// toPrimitive(default) valueOf -> toString
default
user +1: 1000

// toPrimitive(string) toString -> valueOf
string
String(user): toString

// 直接调用toString
toString

调用 obj[Symbol.toPrimitive](hint) 如果这个方法存在,由toPrimitive返回。 不存在按照下面的处理。

js 复制代码
if (hint === "number" || hint === "default") {
  return isBasicType(this.valueOf()) || this.toString();
}

if (hint === "string") {
  return isBasicType(this.toString()) || this.valueOf();
}

valueOf toString

valueOf

对于基础类型的数据,直接返回该类型

string number boolean null undefined symbol

对于非原始值的重写规则如下

对象 valueOf的返回值
Array 数组本身
*Boolean 布尔值
*Date 返回毫秒形式的时间戳
Function 函数本身
*Number 数字值
Object 对象本身
*String 字符串值

注意:String Number Boolean Date 不返回自己

toString转换规则

对象 toString的返回值
Array 以逗号分割的字符串,如[1,2]的toString返回值为"1,2"
Boolean "true" "false"
Date 可读的时间字符串,如"Tue Oct 15 2019 12:20:56 GMT+0800 (中国标准时间)"
Function 声明函数的JS源代码字符串
Number "数字值"
Object "[object Object]"
String "字符串"

注意:前提是原型上有toString,像null undefined调用不了。

检验一下

js 复制代码
var bar=true;
console.log(bar+0);
console.log(bar+"xyz");
console.log(bar+true);
console.log(bar+false);
console.log('1'>bar);
console.log(1+'2'+false);
console.log('2' + ['str',1]);

var obj1 = {
   a:1,
   b:2
}
console.log('2'+obj1);

var obj2 = {
    toString:function(){
        return 'a'
    }
}
console.log('2'+obj2)

NaN

  • 无穷大除以无穷大
  • 给任意负数做开方运算
  • 算数运算符与不是数字或无法转换为数字的操作数一起使用
  • 字符串解析成数字
js 复制代码
Infinity / Infinity;   // 无穷大除以无穷大
Math.sqrt(-1);         // 给任意负数做开方运算
'a' - 1;               // 算数运算符与不是数字或无法转换为数字的操作数一起使用
'a' * 1;
'a' / 1;
parseInt('a');         // 字符串解析成数字
parseFloat('a');

Number('a');   //NaN
'abc' - 1   // NaN
undefined + 1 // NaN
//一元运算符(注意点)
+'abc' // NaN
-'abc' // NaN

自动转换为 string 类型

字符串的自动转换,主要发生在字符串的加法运算时。 当一个值为字符串,另一个值为非字符串,转换未字符串。

js 复制代码
'2' + 1 // '21'
'2' + true // "2true"
'2' + false // "2false"
'2' + undefined // "2undefined"
'2' + null // "2null"


//toString的对象
var obj2 = {
    toString:function(){
        return 'a'
    }
}
console.log('2'+obj2)
//输出结果2a

//常规对象
var obj1 = {
   a:1,
   b:2
}
console.log('2'+obj1);
//输出结果 2[object Object]

//几种特殊对象
'2' + {} // "2[object Object]"
'2' + [] // "2"
'2' + function (){} // "2function (){}"
'2' + ['abc',1] // 2abc,1

自动转换为 number 类型

有加法运算符,但是无 String 类型的时候,都会优先转换为 Number 类型

js 复制代码
true + 0; // 1
true + true; // 2
true + false; //1

"5" - "2"; // 3
"5" * "2"; // 10
true - 1; // 0
false - 1; // -1
"1" - 1; // 0
"5" * []; // 0
false / "5"; // 0
"abc" - 1; // NaN
null + 1; // 1
undefined +
  1 + // NaN
  //一元运算符(注意点)
  "abc" - // NaN
  "abc" + // NaN
  true - // 1
  false; // 0

注意:null 转为数值时为 0,而 undefined 转为数值时为 NaN。

什么时候进行布尔转换

js 复制代码
if (!undefined && !null && !0 && !NaN && !"") {
  console.log("true");
} // true

//下面两种情况也会转成布尔类型
expression ? true : false;
!!expression;

还是说一下==

== 抽象相等比较与+运算符不同,不再是 String 优先,而是 Number 优先。

js 复制代码
var obj1 = {
    valueOf:function(){
        return '1'
    }
}
1 == obj1  //true
//obj1转为原始值,调用obj1.valueOf()
//返回原始值'1'
//'1'toNumber得到 1 然后比较 1 == 1
[] == ![] //true
//[]作为对象ToPrimitive得到 ''
//![]作为boolean转换得到0
//'' == 0
//转换为 0==0 //true


//boolean 先转成number,按照上面的规则得到1
//3 == 1 false
//0 == 0 true
3 == true // false
'0' == false //true
相关推荐
Ai行者心易4 分钟前
10天!前端用coze,后端用Trae IDE+Claude Code从0开始构建到平台上线
前端·后端
东东23312 分钟前
前端开发中如何取消Promise操作
前端·javascript·promise
掘金安东尼17 分钟前
官方:什么是 Vite+?
前端·javascript·vue.js
柒崽18 分钟前
ios移动端浏览器,vh高度和页面实际高度不匹配的解决方案
前端
渣哥34 分钟前
你以为 Bean 只是 new 出来?Spring BeanFactory 背后的秘密让人惊讶
javascript·后端·面试
烛阴43 分钟前
为什么游戏开发者都爱 Lua?零基础快速上手指南
前端·lua
大猫会长1 小时前
tailwindcss出现could not determine executable to run
前端·tailwindcss
Moonbit1 小时前
MoonBit Pearls Vol.10:prettyprinter:使用函数组合解决结构化数据打印问题
前端·后端·程序员
533_1 小时前
[css] border 渐变
前端·css
云中雾丽1 小时前
flutter的dart语言和JavaScript的消息循环机制的异同
前端