js中的隐式类型转换有哪些
目录
- 一、隐式类型转换条件
- 二、== 的隐式类型转换
- 三、+ 的隐式类型转换
- 四、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; // truevar 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 的隐式类型转换
- 如果部署了 [Symbol.toPrimitive] 方法,优先调用再返回;
- 若不存在 [Symbol.toPrimitive] 方法,则调用 valueOf 方法,如果返回基础数据类型,则执行结束;
- 否则调用 toString 方法,如果转换为基础数据类型,则返回;
- 最后,如果都没有返回基础数据类型,则报错。
测试:
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=510 + {}; // '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]'
相关文章:
js中的隐式类型转换有哪些
目录一、隐式类型转换条件二、 的隐式类型转换三、 的隐式类型转换四、object 的隐式类型转换探讨 object 的隐式转换执行顺序探讨 Symbol.toPrimitive 属性如何将对象转换为原始值在前端js这门动态弱类型语言中,不仅存在着显示类型转换,还存在许多隐式类…...
WuThreat身份安全云-TVD每日漏洞情报-2023-02-17
漏洞名称:IBM Aspera Faspex 预身份验证 RCE 漏洞 漏洞级别:高危 漏洞编号:CVE-2022-47986 相关涉及:IBM Aspera Faspex 漏洞状态:POC 参考链接:https://tvd.wuthreat.com/#/listDetail?TVD_IDTVD-2023-02805 漏洞名称:Kardex Mlog MCC PATH 遍历 漏洞级别:严重 漏洞编号:CVE…...
掌握MySQL分库分表(三)水平分库分表常见策略range、hash
文章目录range策略Range策略延伸基于Range范围分库分表业务场景hash取模案例规则水平分库分表,根据什么规则进行划分? range策略 自增id,根据ID范围进行分表(左闭右开) 规则案例: 1~1,000,000 是 table…...
CTFer成长之路之CTF中的SQL注入
CTF中的SQL注入CTF SQL注入 SQL注入-1 题目描述: 暂无 docker-compose.yml version: 3.2services:web:image: registry.cn-hangzhou.aliyuncs.com/n1book/web-sql-1:latestports:- 80:80启动方式 docker-compose up -d 题目Flag n1book{union_select_is_so_cool} Wri…...
python snap7读写PLC
主要在DB块里操作 读DB块 import snap7 import structdef plc_connection():PLC_IP 192.168.10.10PLC snap7.client.Client()PLC.connect(PLC_IP, rack0, slot1)return PLCPLC plc_connection()PLC.read_area()方法从PLC中读取指定区域的数据。 1200表示DB块的编号&#x…...
使用物联网进行智能能源管理的10大优势
如今,物联网推动了许多行业的自动化流程和运营效率,而物联网在能源领域的应用尤其受到消费者、企业甚至政府的关注。除了对电力供应链的诸多好处之外,物联网能源管理系统还让位于新的智能电网,并有望实现更高的安全性和效率。基于…...
工业4.0和工业物联网如何协同工作
虽然许多公司已经接受了工业物联网,但他们现在必须接受工业4.0对数据驱动的数字化转型的承诺。随着制造业、能源、公用事业和供应链应用迅速采用工业物联网(IIoT),这些行业的新现实正在形成。工业物联网提供了企业管理数千个活动部件所需的数据类型&…...
Python机器学习入门笔记(3)—— 线性回归
目录 线性回归 算法简述 LinearRegression() API SGDRegressor API LinearRegression() 和 SGDRegressor对比 过拟合与欠拟合 岭回归 应用场景 线性回归 算法简述 线性回归是一种基本的机器学习算法,它用于建立自变量和因变量之间的线性关系模型。它假设…...
Java:顶级Java应用程序服务器 — Tomcat、Jetty、GlassFish、WildFly
如果你想编写Java web应用程序,首先需要做出一个艰难的决定:选择运行应用程序的Java应用程序服务器。什么是应用服务器?一般来说,应用程序服务器执行Java应用程序。在操作系统中启动它们,然后将应用程序部署到其中。将应用程序服…...
如何在SpringBoot项目上让接口返回数据脱敏,一个注解即可
1 背景需求是某些接口返回的信息,涉及到敏感数据的必须进行脱敏操作2 思路①要做成可配置多策略的脱敏操作,要不然一个个接口进行脱敏操作,重复的工作量太多,很显然违背了“多写一行算我输”的程序员规范。思来想去,定…...
python 之 海龟绘图(turtle)
注:从个人博客园移植而来 使用简介 python 2.6引入的一个简单的绘图工具,俗称为海龟绘图。3.x以上使用的话,可通过pip进行安装,命令为: pip/pip3 install turtle如果出现如下错误: 解决方式: …...
RT-Thread SPI使用教程
RT-Thread SPI 使用教程 实验环境使用的是正点原子的潘多拉开发板。 SPI从机设备使用的是BMP280温湿度大气压传感器。 使用RT-Thread Studio搭建基础功能。 1. 创建工程 使用RT-Thread Studio IDE创建芯片级的工程。创建完成后,可以直接编译下载进行测试。 2.…...
shiro使用——整合spring
shiro使用——整合spring 1. 引入相关配置 <dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.9.1</version></dependency>2. 自定义Realm类 继承AuthorizingRealm 并重写相…...
2023-02-20 leetcode-AccountsMerge
摘要: 记录对leetcode-AccountsMerge的反思 要求: Given a list accounts, each element accounts[i] is a list of strings, where the first element accounts[i][0] is a name, and the rest of the elements are emails representing emails of the account. * Now, w…...
中国高速公路行业市场规模及未来发展趋势
中国高速公路行业市场规模及未来发展趋势编辑中国高速公路行业市场规模正在迅速增长。随着中国经济的快速发展和城市化的加速,对交通基础设施的需求也在不断增加。高速公路是最有效的交通工具,可以大大缩短交通时间,提高出行效率。因此&#…...
佳能iC MF645CX彩色激光多功能打印机报E302-0001故障码检修
故障现象: 一台佳能iC MF645CX彩色激光多功能一体机开机报E302-0001故障代码,如果设备未恢复,请联系经销商或客户支持中心。 维修分析: 佳能iC MF645CX彩色激光多功能一体机开机报E302-0001故障代码的...
加密越来越简单——用JavaScript实现数据加密和解密
加密越来越简单——用JavaScript实现数据加密和解密概念常用算法1. MD5加密算法2. SHA-1加密算法3. AES加密算法代码示例结论总结在当今互联网的世界中,安全性越来越受到关注,数据加密成为了必不可少的一环。Javascript作为前端开发的主要语言之一&#…...
线程池的使用场景
学习整理线程池的使用场景。...
图像分割算法
图像分割算法阈值分割固定阈值自适应阈值大津阈值(OTSU)最大熵阈值连通域分析区域生长分水岭阈值分割、连通域分析、区域生长、分水岭 阈值分割 固定阈值、自适应阈值(adaptiveThreshold)、大津阈值(OTSU)、最大熵阈值(KSW) 固定阈值 固定阈值的调用函数: //Input…...
《mysql技术内幕:innodb存储引擎》笔记
任何时候Why都比What重要;不要相信任何的“神话”,学会自己思考;不要墨守成规,大部分人都知道的事情可能是错误的;不要相信网上的传言,去测试,根据自己的实践做出决定;花时间充分地思考,敢于提出质疑。1.MYSQL被设计为一个单进程多…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
