记癌丝-类型转换

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

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

== 和 === 的区别

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

===不允许

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

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
相关推荐
下雪了 ~30 分钟前
HTTP和HTTPS的区别有哪些?
服务器·前端·笔记·网络协议·计算机网络
跟我很快乐1 小时前
JavaScript ES6+ 语法速通
javascript·es6
修谦得益1 小时前
JavaScript是按顺序执行的吗?聊聊JavaScript中的变量提升
javascript·js变量提升·词法环境
Krorainas1 小时前
将PDF流使用 canvas 绘制然后转为图片展示在页面上(二)
前端·javascript·pdf·react
吉吉安1 小时前
使用echarts实现3d柱状图+折线图
前端·javascript·echarts
yanlele2 小时前
企业级 AI Coding 已经来临, 目前其发展可能已经超越想象,对此我的一些思考
前端·后端·openai
m0_748244832 小时前
WebSpoon9.0(KETTLE的WEB版本)编译 + tomcatdocker部署 + 远程调试教程
前端
大饼酥2 小时前
使用Nexus3搭建npm私有仓库
前端·npm·node.js
CodeToGym2 小时前
React 入门:JSX语法详解
javascript·react.js·ecmascript
苦逼的猿宝2 小时前
React+Antd修改Table组件滚动条样式
前端·javascript·react.js