记癌丝-类型转换

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

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

== 和 === 的区别

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

===不允许

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

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
相关推荐
却尘2 小时前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js
ccnocare2 小时前
浅浅看一下设计模式
前端
Lee川2 小时前
🎬 从标签到屏幕:揭秘现代网页构建与适配之道
前端·面试
Ticnix2 小时前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人3 小时前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl3 小时前
OpenClaw 深度技术解析
前端
崔庆才丨静觅3 小时前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人3 小时前
vue3使用jsx语法详解
前端·vue.js
天蓝色的鱼鱼3 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端
布列瑟农的星空3 小时前
前端都能看懂的Rust入门教程(三)——控制流语句
前端·后端·rust