Advanced-Frontend/Daily-Interview-Question

第 116 题:输出以下代码运行结果

yygmind opened this issue · 34 comments

1 + "1"

2 * "2"

[1, 2] + [2, 1]

"a" + + "b"
'11'
 4
'1,22,1'
'aNaN'

//"a" + + "b"其实可以理解为
//   + "b" -> NaN
//“a”+NaN

11
4
1,22,1
aNaN

求讲解

最后一个不懂

"a" + + "b"
"aNaN"
这个是为啥

"a" + + "b"
"aNaN"
这个是为啥

"a" + + "b" 是先+"b", 所以是NaN => "a" + NaN => "aNaN"

  • 'b'为什么是NaN
  • 1 + "1"

加性操作符:如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来

所以值为:“11”

  • 2 * "2"

乘性操作符:如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值

  • [1, 2] + [2, 1]

Javascript中所有对象基本都是先调用valueOf方法,如果不是数值,再调用toString方法。

所以两个数组对象的toString方法相加,值为:"1,22,1"

  • "a" + + "b"

后边的“+”将作为一元操作符,如果操作数是字符串,将调用Number方法将该操作数转为数值,如果操作数无法转为数值,则为NaN。

所以值为:"aNaN"

以上均参考:《Javascript高级程序设计》

难度一般
+"b" => NAN
+(正)-(负)!, ++,--
优先级 比+、-、*、/ 运算优先级高

"a" + + "b" 相当于 "a" + Number("b")

  • 1 + "1"

加性操作符:如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来

所以值为:“11”

  • 2 * "2"

乘性操作符:如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值

  • [1, 2] + [2, 1]

Javascript中所有对象基本都是先调用valueOf方法,如果不是数值,再调用toString方法。

所以两个数组对象的toString方法相加,值为:"1,22,1"

  • "a" + + "b"

后边的“+”将作为一元操作符,如果操作数是字符串,将调用Number方法将该操作数转为数值,如果操作数无法转为数值,则为NaN。

所以值为:"aNaN"

以上均参考:《Javascript高级程序设计》

mark 一下

lhyt commented

很基础的题目,不过数组那个case有点不一样,它最后还会再执行join方法进行隐式转换

const arr = [1,2,3]
const { toString, valueOf, join } = arr

arr.toString = function(...args) {
  console.log('tostring');
  return toString.call(arr, ...args)
}

arr.valueOf = function(...args) {
  console.log('valueOf');
  return valueOf.call(arr, ...args)
}

arr.join = function(...args) {
  console.log('join');
  return join.call(arr, ...args)
}

arr + [4,5,6]

更多类型转换相关可见这里

稍稍补充一小下:
加号作为一元运算符时,其后面的表达式将进行ToNumber(参考es规范)的抽象操作:

  • true -> 1
  • false -> 0
  • undefined -> NaN
  • null -> 0
  • ’字符串‘ -> 字符串为纯数字时返回转换后的数字(十六进制返回十进制数),否则返回NaN
  • 对象 -> 通过ToPrimitive拿到基本类型值,然后再进行ToNumber操作
+true  // 1
+false // 0
+undefined // NaN
+null // 0
+'b'    // NaN
+'0x10' // 16
+{valueOf: ()=> 5} // 5
  • 1 + "1"

加性操作符:如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来

所以值为:“11”

  • 2 * "2"

乘性操作符:如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值

  • [1, 2] + [2, 1]

Javascript中所有对象基本都是先调用valueOf方法,如果不是数值,再调用toString方法。

所以两个数组对象的toString方法相加,值为:"1,22,1"

  • "a" + + "b"

后边的“+”将作为一元操作符,如果操作数是字符串,将调用Number方法将该操作数转为数值,如果操作数无法转为数值,则为NaN。

所以值为:"aNaN"

以上均参考:《Javascript高级程序设计》

补充一下:js中一元加的优先级高于2元加,第四问主要考查的是js的运算优先级
运算优先级

image

  • 我有个问题,加法运算符是从左到右运算的,"a" + + "b"
  • ① ("a" + )+ "b" =>结果报错
  • ② "a" +( + "b") => 先算 + "b" 得 aNaN
  • ③ "a" + (+"b") => 把+“b”看出整体,的aNaN
    我的问题是,为什么不是第一个。而是第三个呢?

"11"
4
"1,22,1"
"aNaN"

最后一个不懂

关于第四个为何+“b”等于“NaN”,大家可以参考这里

原理是:

  1. 首先一元运算符+优先级高于二元运算符+,原式等于"a" + ( +"b");

  2. 而+“b”可以看上面的链接,对于类似"2b"、“b”、“b2”不是纯数字的串,进行一元加运算时无法转化为数字,返回“NaN”。

image

  • 我有个问题,加法运算符是从左到右运算的,"a" + + "b"
  • ① ("a" + )+ "b" =>结果报错
  • ② "a" +( + "b") => 先算 + "b" 得 aNaN
  • ③ "a" + (+"b") => 把+“b”看出整体,的aNaN
    我的问题是,为什么不是第一个。而是第三个呢?

因为一元运算符优先级高。参考

image

  • 我有个问题,加法运算符是从左到右运算的,"a" + + "b"
  • ① ("a" + )+ "b" =>结果报错
  • ② "a" +( + "b") => 先算 + "b" 得 aNaN
  • ③ "a" + (+"b") => 把+“b”看出整体,的aNaN
    我的问题是,为什么不是第一个。而是第三个呢?

因为一元运算符优先级高。参考

这个我知道啊,你说说优先级怎么样?

  • 1 + "1"

加性操作符:如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来

所以值为:“11”

  • 2 * "2"

乘性操作符:如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值

  • [1, 2] + [2, 1]

Javascript中所有对象基本都是先调用valueOf方法,如果不是数值,再调用toString方法。

所以两个数组对象的toString方法相加,值为:"1,22,1"

  • "a" + + "b"

后边的“+”将作为一元操作符,如果操作数是字符串,将调用Number方法将该操作数转为数值,如果操作数无法转为数值,则为NaN。

所以值为:"aNaN"

以上均参考:《Javascript高级程序设计》

mark too

1 + "1"
//"11"
2 * "2"
//4
[1, 2] + [2, 1]
//"1,22,1"
"a" + + "b"
//"aNaN"

今天的题目还是比较简单

  1. 字符串拼接
1 + '1'  // '1' + '1'  ->  11  
  1. 隐式转换为数字
2 * '2'  // 2 * 2  ->  4
  1. 依旧是字符拼接 [].toString()
[1, 2] + [2, 1]  // '1, 2' + '2, 1'  ->  1, 22, 1
  1. 依旧是隐式转换为数字,再做拼接 + 'b' -> NaN
'a' + + 'b'  // 'a' + NaN  ->  'aNaN'

另外

  1. 表达式有多个带间隔的+/-时会从后至前依次进行正负运算操作
let a = 1;
let b = 2;
a + + - + - - + - b  // 3
  1. 两个连续不间断的+/-会被判定为自增/自减运算符
let a = 1;
let b = 2;
a ++ - - ++ b  // 1 - -3  -> 4
zwmmm commented

算术运算符 MDN

终于有个明白人 一元运算符居然有这么多人不知道

console.log( 1 + "1" )
//11
console.log( 2 * "2" )
//4
console.log([1, 2] + [2, 1])
//[3,3]. [1,2,1]
console.log("b" + + "a")
//"a b" [aNaN]

1 + "1" //11

2 * "2" // 4

[1, 2] + [2, 1] // 相当于转成stirng,所以12+21=1221

"a" + + "b" // +‘b’隐式转换为NaN,'a'+NaN=aNaN

关于这个 "a" + + "b" 为aNaN,是因为第二个+号是正号的意思,一元运算符(单目运算符的优先级高于双目运算符),+"b" ,"b"隐式转换number类型所以aNaN

指针最优,单目运算优于双目运算。如正负号。
先算术运算,后移位运算,最后位运算。请特别注意:1 << 3 + 2 & 7等价于 (1 << (3 + 2))&7.
逻辑运算最后结合。

以上来自百度

  • 'b'为什么是NaN

+"b" =>Number("b")=>NaN

摘抄
对数字进行一元加操作,结果返回数字本身,要注意对负数进行一元加操作结果还是负数啦,不要以为会得到整数;
对布尔类型进行一元加操作,true的话返回1,false返回0;
对null进行一元加操作,返0;
对undefined进行一元加操作,返回NaN;
对字符串进行一元加操作,有两种结果,如果字符串由纯数字构成的话,返回1,如果不是则返回NaN;
对对象进行一元加操作,也有两种结果,一是返回数字,二是返回NaN;操作过程中首先会调用valueOf方法,如果得不到数字结果,就调用toString方法,再对得到的字符串进行一元加操作;

摘抄
对数字进行一元加操作,结果返回数字本身,要注意对负数进行一元加操作结果还是负数啦,不要以为会得到整数;
对布尔类型进行一元加操作,true的话返回1,false返回0;
对null进行一元加操作,返0;
对undefined进行一元加操作,返回NaN;
对字符串进行一元加操作,有两种结果,如果字符串由纯数字构成的话,返回1,如果不是则返回NaN;
对对象进行一元加操作,也有两种结果,一是返回数字,二是返回NaN;操作过程中首先会调用valueOf方法,如果得不到数字结果,就调用toString方法,再对得到的字符串进行一元加操作;

属性访问 > 一元操作符 > 乘除 > 加减 > 比较 > 相等 > 与运算 > 或运算 > 三目运算 > 赋值运算

输出以下代码运行结果

1 + "1"

2 * "2"

[1, 2] + [2, 1]

"a" + + "b"
  1. 加性操作符:如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来 ==> "11"
  2. 乘性操作符:如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值 ==> 4
  3. Javascript中所有对象基本都是先调用valueOf方法,如果不是数值,再调用toString方法。==> '1,2'+'2,1'==> '1,22,1'
  4. 一元操作符'+'的优先级大于加减运算,所以+"b"的结果为NaN,==》 “aNaN”

参考:一元正号运算符位于其操作数前面,计算其操作数的数值,如果操作数不是一个数值,会尝试将其转换成一个数值

+3     // 3
+"3"   // 3
+true  // 1
+false // 0
+null  // 0
+function(val){ return val;} //NaN

很基础的题目,不过数组那个case有点不一样,它最后还会再执行join方法进行隐式转换

const arr = [1,2,3]
const { toString, valueOf, join } = arr

arr.toString = function(...args) {
  console.log('tostring');
  return toString.call(arr, ...args)
}

arr.valueOf = function(...args) {
  console.log('valueOf');
  return valueOf.call(arr, ...args)
}

arr.join = function(...args) {
  console.log('join');
  return join.call(arr, ...args)
}

arr + [4,5,6]

更多类型转换相关可见这里

其实是数组的toString方法里面调用的join方法,而不是本身就调用了join。在你的例子最下面加上console.log('test :>> ', arr.toString());可以看出join也打印了

1 - '1' = 0
1 / '1' = 1

1 + "1" // '11'

2 * "2" // 4

[1, 2] + [2, 1] // '1,22,1'

"a" + + "b" // 'aNaN'


1 + '1' :存在字符串时,+ 会进行字符串拼接
2 * "2" :乘法操作,"2" 会转化为数字,如果转换失败,会是 NaN
[1, 2] + [2, 1]:加法操作,[1, 2]  [2, 1] 是对象,会先调用 toString 方法,变成 "1,2" + "2,1"
"a" + + "b":可以分开来看,"a" + (+"b") => "a" + NaN =>  "aNaN"