JavaScript中[]+[] 、[]+{}、{}+[]、{}+{}的结果分析
看到这样一个问题:{} + [] 的结果是多少? 一脸懵逼..
于是在chrome控制台运行 {} + [] 和用 console.log({} + []) 输出,发现结果不一样..
于是,把各种可能的情况都考虑了一下:
//情形一:控制台直接输出
[]+[] //""
[]+{} //"[object Object]"
{}+[] //
{}+{} //NaN //情形二:括号语句里面输出
([]+[]); //""
([]+{}); //"[object Object]"
({}+[]); //"[object Object]"
({}+{}); //"[object Object][object Object]" //情形三:console.log()输出
console.log([]+[]); //空
console.log([]+{}); //[object Object]
console.log({}+[]); //[object Object]
console.log({}+{}); //[object Object][object Object] //输出结果长度
console.log(([]+[]).length); //
console.log(([]+{}).length); //
console.log(({}+[]).length); //
console.log(({}+{}).length); //
为什么结果会是这样的呢?被绕晕了。
首先情形二和情形三很简单,情形三就是将情形二中得到的字符串通过console.log()指令输出,最后输出的长度就是情形二中求得的 字符串的长度。
现在重点考虑,情形一和情形二的区别。
加号运算符———值的类型转换原理
Javascrip基本数据类型Undefined
、Null
、Boolean
、Number
和String,引用数据类型Object类型,其中
Object
包括array跟function。
加号运算符能执行三种转换:把值转化成基本数据类型,数字和字符串。
//a、b类型不确定
a+b;
(1)如果a 、b都为基本数据类型,直接按基本类型参与运算
(2)如果a或者b是对象类型,首先调用对象的 valueOf
方法,如果返回一个基本类型,则以该基本类型参与运算;否则调用 toString
方法,返回基本类型则参与运算
一个例外是 Date 的实例,其实例首先调用 toString
,接着才调用 valueOf
。
(3)否则,抛出错误TypeError
回到最开始的问题
(1)数组与数组相加
[]+[] //"" [].valueOf(); //[]
[].toString(); //""
数组的 valueOf()方法
返回自身,因此不是基本类型,接着调用 toString()方法
,空数组返回空字符串。 [1,2].toString(); // "1,2"
(2)数组与对象相加
[]+{} //"[object Object]" [].valueOf(); //[]
[].toString(); //"" ({}).valueOf(); //object {}
({}).toString(); //"[object Object]"
对象和数组转换原理一样,普通对象的toString()方法始终返回字符串 “[object Object]”,所以有 “”+ “[object Object]”= “[object Object]”。
(3)对象和数组相加、对象和对象相加
{}+[] //
{}+{} //NaN
发现以上方法在这里行不通了,什么原因呢?
问题在于JavaScript把第一个{},解析成空的代码块并且忽略它了。{}+[] 可以看成 +[] 、{}+{}可以看成+{}。
现在可以明白了,+[] 这里的加号并不是二元元素符的那个加号,而是一元运算符,作用是,把值转换为Number
,跟Number()
方法一样。
Number([]); //
Number({}); //NaN
//+{} 等价于
Number({})
Number({}.toString()) // {}.valueOf() isn’t primitive
Number("[object Object]")
NaN
为什么第一个{}会被解析成代码块呢?因为这{}在这个声明的起始,所以被当成复合语句块了。
当{}既可以被理解为复合语句块也可以被理解为对象直接量或函数声明的时候,JavaScript将会将其理解成为复合语句块。
然后,怎么修复呢??
问题引到情形二的情况,括号语句里面输出,即强制解析器把它认为是表达式。 js把()中的语句当做一个表达式 JS高程P185
因此{}不能被理解为语句块,而被理解为"[object Object]" + "",console.log("[object Object]"+"")打印结果为[object Object]。
({}+[]); //"[object Object]"
({}+{}); //"[object Object][object Object]"
参考资料:
{}+[]与console.log({}+[])结果不同?从JavaScript的大括号谈起
JavaScript中[]+[] 、[]+{}、{}+[]、{}+{}的结果分析的更多相关文章
- 简单分析JavaScript中的面向对象
初学JavaScript的时候有人会认为JavaScript不是一门面向对象的语言,因为JS是没有类的概念的,但是这并不代表JavaScript没有对象的存在,而且JavaScript也提供了其它的方 ...
- JavaScript中的ParseInt("08")和“09”返回0的原因分析及解决办法
今天在程序中出现一个bugger ,调试了好久,最后才发现,原来是这个问题. 做了一个实验: alert(parseInt("01")),当这个里面的值为01====>07时 ...
- javascript中call,apply,bind的用法对比分析
这篇文章主要给大家对比分析了javascript中call,apply,bind三个函数的用法,非常的详细,这里推荐给小伙伴们. 关于call,apply,bind这三个函数的用法,是学习java ...
- C#保留2位小数几种场景总结 游标遍历所有数据库循环执行修改数据库的sql命令 原生js轮盘抽奖实例分析(幸运大转盘抽奖) javascript中的typeof和类型判断
C#保留2位小数几种场景总结 场景1: C#保留2位小数,.ToString("f2")确实可以,但是如果这个数字本来就小数点后面三位比如1.253,那么转化之后就会变成1.2 ...
- Javascript中,实现类与继承的方法和优缺点分析
Javascript是一种弱类型语言,不存在类的概念,但在js中可以模仿类似于JAVA中的类,实现类与继承 第一种方法:利用Javascript中的原型链 //首先定义一个父类 function An ...
- javaScript中with函数用法实例分析
javaScript 中的 with 函数 ,即所谓的with 语句,可以方便地用来引用某个特定对象中已有的属性,但是不能用来给对象添加属性,要给对象创建新的属性,必须明确地引用该对象. with 函 ...
- js实例分析JavaScript中的事件委托和事件绑定
我们在学习JavaScript中,难免都会去网上查一些资料.也许偶尔就会遇到“事件委托”(也有的称我“事件代理”,这里不评论谁是谁非.以下全部称为“事件委托”),尤其是在查JavaScript的事件处 ...
- javascript中基本类型和引用类型的区别分析
大多数人系统学习过的程序设计语言,在这些语言的学习过程中最早学到的几个要点之一就是值类型和引用类型的区别.下面我们来看一下在 JavaScript 中基本数据类型(Primitive Types)和引 ...
- 前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型
前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...
随机推荐
- Caffe系列2——Windows10制作LMDB数据详细过程(手把手教你制作LMDB)
Windows10制作LMDB详细教程 原创不易,转载请注明出处:https://www.cnblogs.com/xiaoboge/p/10678658.html 摘要: 当我们在使用Caffe做深度 ...
- Codeforces Parking Lot
http://codeforces.com/problemset/problem/630/I 简单的排列组合,推式子技巧:举一个小样例,看着推,别抽象着推,容易错 #include <iostr ...
- day2-元组、字典、文件操作
学习内容: 1. 元组操作 2. 字典操作 3. 文件操作 4. 深浅copy 1. 元组操作: 元组和列表非常相似,只不过元组不能在原处修改(它是不可变的),并且通常写成圆括号中的一系列项. # 元 ...
- Python-数据类型内置方法(2)
目录 元组(tuple) 内置方法: 字典(dict) 内置方法: 优先掌握: 需要掌握 集合(set) 优先掌握 深浅拷贝 拷贝(赋值) 浅拷贝 深拷贝 总结 存值个数 有序 or 无序 可变 or ...
- MyEclipse使用总结——MyEclipse安装maven插件[转]
打开 myeclipse, MyEclipse --> Preferences -->Maven4MyEclipse 确定jdk是可用的 选择自己安装的maven: 点击Add选中我们的 ...
- opencv-阈值分割
关于自适应阈值,可参考:Wellner 自适应阈值二值化算法 一.大津法OTSU(最大类间方差法) 参考:非黑即白——图像分割入门篇之Otsu阈值 自适应阈值分割—大津法(OTSU算法)C++实现 灰 ...
- typedef int (init_fnc_t) (void)和typedef int (*init_fnc_t) (void)
1.typedef int (init_fnc_t) (void);表示定义init_fnc_t为函数类型,该函数返回int型,无参数.而“init_fnc_t *init_sequence[]= ...
- 《DSP using MATLAB》Problem 8.4
今天是六一儿童节,陪伴不了家人,心里思念着他们,看着地里金黄的麦子,远处的山,高高的天 代码: %% ------------------------------------------------- ...
- 封装了一个HOOKAPI的类。。。
我惊奇地发现,我手竟然这么生了..... 很久很久没有写这方面的东西,现在写着竟然这么手生....哎.... 这玩艺,还得天天练....
- 嘴巴题6 BZOJ3450JoyOI1952 Easy
Time Limit: 10 Sec Memory Limit: 128 MB Submit: 936 Solved: 698 [Submit][Status][Discuss] Descriptio ...