记癌丝-类型转换

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

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

== 和 === 的区别

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

===不允许

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

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
相关推荐
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang1 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、4 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser6 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui