js中的隐式类型转换有哪些

news2024/11/15 16:31:20

目录

  • 一、隐式类型转换条件
  • 二、== 的隐式类型转换
  • 三、+ 的隐式类型转换
  • 四、object 的隐式类型转换
      • 探讨 object 的隐式转换执行顺序
      • 探讨 Symbol.toPrimitive 属性如何将对象转换为原始值

在前端js这门动态弱类型语言中,不仅存在着显示类型转换,还存在许多隐式类型转换,让人头大。为了减少小伙伴们的踩坑,今天总结了一些常见的隐式类型转换规则,让我们来看看有哪些。

一、隐式类型转换条件

  • 逻辑运算符:&&、||、!
  • 运算符:+、-、*、/
  • 关系操作符:>、<、<=、>=
  • 相等运行算符:==
  • if / while 条件

二、== 的隐式类型转换

  • 类型相同,则无需进行类型转换。
  • 如果其中一个操作数是 null 或者 undefined ,那么另一个操作数必须是 null 或者 undefined 才会返回 true ,否则返回 false 。
  • 如果其中一个操作数是 Symbol ,那么返回 false。
  • 如果两个操作数都为 string 和 number 类型,那就就将字符串转换为 number。
  • 如果一个操作数是 boolean 类型,那么转换成 number。
  • 如果一个操作数为 object ,且另一方为 string、number、或者 Symbol ,就会把object 转换为原始类型再进行判断。

测试:

null == undefined;  // true
null == 0;  		// false
'' == null;  		// false
'' == 0;  			// true
'123' == 123;  		// true
0 == false;  		// true
1 == true;  		// true

var a = {
	value: 0,
	valueOf: function(){
		this.value++;
		return this.value;
	}
}
console.log(a==1 && a==2 && a==3);  // true
// 对象隐式转换为原始类型,调用对象的valueOf方法返回值,此对象的valueOf()返回一个自定义自增方法,每调用一次增加1,最后结果为3.
// a==1时,a.valueOf()返回1,所以1==1为true,此时a.value==1;
// a==2时,a.valueOf()返回2,所以2==2为true,此时a.value==2;
// a==3时,a.valueOf()返回3,所以3==3为true,此时a.value==3;

// 这时,如果再判断a==1&&a==2&&a==3,则返回false,因为此时的a已经为4了
console.log(a==1 && a==2 && a==3);  // false

三、+ 的隐式类型转换

+号操作符,不仅可以用作数字相加,还可以用作字符串拼接。

  • 如果其中一个操作数是 string,另外一个操作数是 undefined、null 或者 boolean,则调用 toString() 方法进行字符串拼接
  • 如果是纯对象、数组、正则等,则默认调用对象的转换方法,会存在优先级,然后再进行拼接。
  • 如果其中有一个是 number ,另外一个是 undefined、null、boolean、number,则会将其转换为数字进行加法运算,对象的情况参考上一条规则。
  • 如果其中一个是 string ,一个是 number,则按照字符串规则进行拼接。

测试:

1 + 2;      // 3
'1' + '2';  // '12' 
'1' + 3;    // '13' 字符串拼接

'1' + undefined;  // '1undefined'
'1' + null;       // '1null'
'1' + true;       // '1true'
'1' + 1n;         // '11' 字符串和BigInt相加,BigInt转换为字符串

1 + undefined;  // NaN  undefined转换为NaN
1 + null;       // 1  null转换为0
1 + true;       // 2  true转换为1
1 + 1n;         // TypeError: Cannot mix BigInt and other types, use explicit conversion "无法混合BigInt和其他类型,请使用显式转换"

四、object 的隐式类型转换

  1. 如果部署了 [Symbol.toPrimitive] 方法,优先调用再返回;
  2. 若不存在 [Symbol.toPrimitive] 方法,则调用 valueOf 方法,如果返回基础数据类型,则执行结束;
  3. 否则调用 toString 方法,如果转换为基础数据类型,则返回;
  4. 最后,如果都没有返回基础数据类型,则报错。

测试:

var obj = {
	value: 1,
	valueOf(){
		console.log('valueOf', 2);
		return 2;
	},
	toString(){
		console.log('toString', 3);
		return 3;
	},
	[Symbol.toPrimitive](){
		console.log('[Symbol.toPrimitive]', 4);
		return 4;
	}
}
console.log(obj + 1);  // 5
// 调用[Symbol.toPrimitive]方法,获取返回值4,4+1=5

10 + {};  // '10[object Object]'
// {}调用valueOf方法返回自身,然后继续调用toString方法返回字符串'[object Object]',10与其相加得 '10[object Object]'

[1, 2, undefined, 4, 5] + 10;  // '1,2,,4,510'
// 数组调用valueOf方法返回数组本身,然后调用toString方法转换为字符串'1,2,,4,5',与10相加得 '1,2,,4,510'

探讨 object 的隐式转换执行顺序

1、有 [Symbol.toPrimitive] 方法,执行方法后获取原始值返回,执行结束;若返回不是原始值则报错。

var obj = {
	value: 1,
	valueOf(){
		console.log('valueOf', 2);
		return 2;
	},
	toString(){
		console.log('toString', 3);
		return 3;
	},
	[Symbol.toPrimitive](){
		console.log('[Symbol.toPrimitive]', 4);
		return 4;
	}
}
console.log(obj + 1);  // 5

在这里插入图片描述
2、valueOf方法返回值不为原始值时,则继续寻找toString方法执行,获取返回值,执行结束。

var obj = {
	value: 1,
	valueOf(){
		console.log('valueOf', 2);
		return {};
	},
	toString(){
		console.log('toString', 3);
		return 3;
	},
}
console.log(obj + 1);  // 4

在这里插入图片描述
3、若valueOf方法返回值为原始值时,执行结束。

var obj = {
	value: 1,
	valueOf(){
		console.log('valueOf', 2);
		return 2;
	},
	toString(){
		console.log('toString', 3);
		return 3;
	}
}
console.log(obj + 1);  // 3

在这里插入图片描述
4、若无 Symbol.toPrimitive 方法,并且最终获取不到原始值时,报错。

var obj = {
	value: 1,
	valueOf(){
		console.log('valueOf {}');
		return {};
	},
	toString(){
		console.log('toString {}');
		return {};
	}
}
console.log(obj + 1);  // ncaught TypeError: Cannot convert object to primitive value

在这里插入图片描述

探讨 Symbol.toPrimitive 属性如何将对象转换为原始值

Symbol.toPrimitive 指将被调用的指定函数值的属性转换为相对应的原始值。

在 Symbol.toPrimitive属性(用作函数值)的帮助下,一个对象可被转换为原始值。该函数由字符串参数 hint 调用,目的是指定原始值转换结果的首选类型。 hint 参数可以是"number"、“string” 和 “default” 中的一种。

// An object without Symbol.toPrimitive property. 对象中不存在Symbol.toPrimitive属性
var obj1 = {};
console.log(+obj1);     // NaN
console.log(`${obj1}`); // "[object Object]"
console.log(obj1 + ''); // "[object Object]"

// An object with Symbol.toPrimitive property. 对象中存在Symbol.toPrimitive属性
var obj2 = {
  [Symbol.toPrimitive](hint) {
    if (hint == 'number') {
      return 10;
    }
    if (hint == 'string') {
      return 'hello';
    }
    return true;
  }
};
console.log(+obj2);     // 10        -- hint is "number"
console.log(`${obj2}`); // "hello"   -- hint is "string"
console.log(obj2 + ''); // "true"    -- hint is "default"

超强测试题:

{} + '';   // 0   
// 代码执行顺序为从左到右,此处的{}被认为是代码块而非对象,所以不进行类型转换,仅剩余 +'' 被转换number类型

+{} + '';  // 'NaN'  
// 此处先执行+{},转换为number类型NaN,与空字符串相加得'NaN'

'' + {};   // '[object Object]'  
// 此处的+号前面空字符串为string类型,按照代码执行顺序以及字符串拼接规则,
// 需将{}转换为string类型与其相加,调用toString方法获得'[object Object]'

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/359380.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

原画培训机构排名前十名,最新10大原画培训机构

原画培训机构排名出来啦&#xff0c;最新10大原画培训机构出炉&#xff0c;快来看看游戏原画培训机构有哪些吧&#xff0c;对于不知道如何选择靠谱的原画培训班&#xff0c;可以借鉴和参考一下&#xff01; 1、轻微课 国内人气很高的板绘学习平台&#xff0c;主打课程有日系插…

化解射频和微波设计挑战的六个技巧

即使是最自信的设计人员&#xff0c;对于射频电路也往往望而却步&#xff0c;因为它会带来巨大的设计挑战&#xff0c;并且需要专业的设计和分析工具。这里将为您介绍六条技巧&#xff0c;来帮助您简化任何射频PCB 设计任务和减轻工作压力&#xff01; 1、保持完好、精确的射频…

从全局变量寻找到Tomcat回显方式

前言 对于回显的获取主要是在ApplicationFilterChain类的lastServicedRequest / lastServicedResponse两个属性&#xff0c;是使用的ThreadLocal进行修饰的&#xff0c;并且&#xff0c;在执行请求的过程中&#xff0c;通过反射修改属性值&#xff0c;能够记录下当前线程的req…

nginx 代理01(持续更新)

1、如果请求是post&#xff0c;而且请求原是188.188.3.171&#xff0c;处理方式403 if ($request_method ~* "POST") # $request_method 等同于request的method&#xff0c;通常是“GET”或“POST” # 如果访问request的method值为POST则返回“o” {set…

MinIO文件系统

3.2 MinIO 3.2.1 介绍 本项目采用MinIO构建分布式文件系统&#xff0c;MinIO 是一个非常轻量的服务,可以很简单的和其他应用的结合使用&#xff0c;它兼容亚马逊 S3 云存储服务接口&#xff0c;非常适合于存储大容量非结构化的数据&#xff0c;例如图片、视频、日志文件、备份…

基于 SmartX 分布式存储的 iSCSI 与两种 NVMe-oF 技术与性能对比

作者&#xff1a;深耕行业的 SmartX 金融团队本文重点SmartX 分布式块存储 ZBS 提供 2 种存算分离架构下的数据接入协议&#xff0c;分别是 iSCSI 和 NVMe-oF。其中&#xff0c;iSCSI 虽然具有很多优势&#xff0c;但不适合支持高性能的工作负载&#xff0c;这也是 SmartX 选择…

《爆肝整理》保姆级系列教程python接口自动化(十九)--Json 数据处理---实战(详解)

简介 上一篇说了关于json数据处理&#xff0c;是为了断言方便&#xff0c;这篇就带各位小伙伴实战一下。首先捋一下思路&#xff0c;然后根据思路一步一步的去实现和实战&#xff0c;不要一开始就盲目的动手和无头苍蝇一样到处乱撞&#xff0c;撞得头破血流后而放弃了。不仅什么…

Java——位运算符

Java——位运算符起因位运算符1.Java中^ 运算符的目的2.Java中& 0xff运算符的目的3.Java中<< 8运算符的目的起因 写这篇文章的起因是在某个地方需要将字节数组byte[]转16进制数字int。见上一篇文章: 进制转换的一些内容&#xff0c;我写出来的方法长这样。 byte[] …

2. RNN 情感评论鉴定

目录1. 加载购物评论数据集2. 构建 RNN 神经网络&#xff08;DNN、CNN、RNN、GNN&#xff09;3. 多循环神经网络原理分析4. LSTM 原理剖析5. LSTM 与 Bi LSTM1. 加载购物评论数据集 file --> setting --> plugins --> Installed --> 搜索【csv Plugin】即可。 …

【前端】浏览器的渲染流程(完整)

本文主要包含以下内容&#xff1a;浏览器渲染整体流程解析 HTML样式计算布局分层生成绘制指令分块光栅化绘制常见面试题浏览器渲染整体流程浏览器&#xff0c;作为用户浏览网页最基本的一个入口&#xff0c;我们似乎认为在地址栏输入 URL 后网页自动就出来了。殊不知在用户输入…

RocketMQ之(一)RocketMQ入门

一、RocketMQ入门一、RocketMQ 介绍1.1 RocketMQ 是什么&#xff1f;1.2 RocketMQ 应用场景01、应用解耦02、流量削峰03、数据分发1.3 RocketMQ 核心组成01、NameServer02、Broker03、Producer04、Consumer1.6 运转流程1.5 RocketMQ 架构01、NameServer 集群02、Broker 集群03、…

NetApp Cloud Volumes ONTAP 将数据复制到云或从云中复制

NetApp Cloud Volumes ONTAP 将数据复制到云或从云中复制&#xff0c;为开发运营和基于云的灾难恢复提供支持。 无论应用位于何处&#xff0c;都可以使用企业级存储,让云存储基础架构更经济、更智能、更合规且更安全。 为什么选择 NetApp Cloud Volumes ONTAP NetApp Cloud …

RocketMQ 第二章

RocketMQ 第二章 7、SpringBoot整合RocketMQ SpringBoot 提供了快捷操作 RocketMQ 的 RocketMQTemplate 对象。 7.1、引入依赖 注意依赖的版本需要和 RocketMQ 的版本相同。 <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rock…

本地部署element-plus文档

由于一直使用的前端组件element-plus&#xff0c;所以需要经常看文档&#xff0c;但无奈官网实在不给力&#xff0c;经常报503或者404&#xff0c;大大影响效率和心情&#xff0c;忍无可忍就本地化部署一套解决此问题。 百度了一下大多数都是使用 vscode的live server, 或者放…

JAVA保姆式JDBC数据库免费教程之02-连接池技术

连接池 连接池概念 ​ 概念&#xff1a;其实就是一个容器(集合)&#xff0c;存放数据库连接的容器。 当系统初始化好后&#xff0c;容器被创建&#xff0c;容器中会申请一些连接对象&#xff0c;当用户来访问数据库时&#xff0c;从容器中获取连接对象&#xff0c;用户访问完…

【MySQL】MySQL 架构

一、MySQL 架构 C/S 架构&#xff0c;即客户端/服务器架构。服务器程序直接和我们存储的数据打交道&#xff0c;多个客户端连接这个服务器程序。客户端发送请求&#xff0c;服务器响应请求。 MySQL 数据库实例 &#xff1a;即 MySQL 服务器的进程 &#xff08;我们使用任务管理…

Vue组件间通信的四种方式(函数回调,自定义事件,事件总线,消息订阅与发布)

目录 概述 props配置项-回调函数实现 自定义事件实现 事件总线实现 消息订阅与发布实现 概述 在组件化编程中&#xff0c;组件间的通信是重要的&#xff0c;我们可以有四种方式实现组件间的通信。 分别是&#xff1a;函数回调&#xff0c;自定义事件&#xff0c;事件总…

可调恒流驱动LED电路分析

https://www.icxbk.com/article/detail?aid884 常规使用的pwm调亮度不仅会导致频闪&#xff0c;而且在长时间使用的时候&#xff0c;有损坏led的风险&#xff0c;所以这次设计了一个恒流调亮度电路&#xff0c;其电路图如下所示 电路原理的解读&#xff1a; 左侧的电位计起着…

【JavaScript】js实现深拷贝的方法

前言 在js中我们想要实现深拷贝&#xff0c;首先要了解深浅拷贝的区别。 浅拷贝&#xff1a;只是拷贝数据的内存地址&#xff0c;而不是在内存中重新创建一个一模一样的对象&#xff08;数组&#xff09; 深拷贝&#xff1a;在内存中开辟一个新的存储空间&#xff0c;完完全全…

Java语言常用哪些运算符?

之前有个大家讨论过java的数据类型&#xff0c;总体来说类型和其他几种语言也相差无几&#xff0c;我为什么会这样说&#xff1f;我们应该都要知道Python可还有个复数类型。 这里主要给大家讲解Java运算符的分类和使用。 一、运算符分类 说到运算符&#xff0c;我们可以先了…