关于javascript:令人头疼的Javascript隐式强制转换

38次阅读

共计 3514 个字符,预计需要花费 9 分钟才能阅读完成。

Javascript 的隐式强制只是指 Javascript 试图将意外的值类型强制为预期的类型。因而,您能够在须要数字的中央传递一个字符串,在须要字符串的中央传递一个对象等,它会尝试将其转换为正确的类型。这是最好防止的 Javascript 性能。

3 * "3" //9
1 + "2" + 1 //121

true + true //2
10 - true //9


const foo = {valueOf: () => 2
}
3 + foo // 5
4 * foo // 8

const bar = {toString: () => "promise is a boy :)"
}
1 + bar // "1 promise is a boy :)"


4 * [] // 0
4 * [2] // 8
4 + [2] // "42"
4 + [1, 2] // "41,2"
4 * [1, 2] // NaN

"string" ? 4 : 1 // 4
undefined ? 4 : 1 // 1

数字表达式中的非数字值

字符串

每当您在波及以下任一运算符的数字表达式中将字符串作为操作数传递时:-, *, /, %,数字的转换过程相似于对值调用内置 Number 函数。这非常简单,任何仅蕴含数字字符的字符串都将转换为其等效的数字,但蕴含非数字字符的字符串将返回NaN. 如下图,

3 * "3" // 3 * 3
3 * Number("3") // 3 * 3
Number("5") // 5

Number("1.") // 1
Number("1.34") // 1.34
Number("0") // 0
Number("012") // 12

Number("1,") // NaN
Number("1+1") // NaN
Number("1a") // NaN
Number("one") // NaN
Number("text") // NaN

+ 运算符的状况

  • 运算符与其余数学运算符不同,执行两个性能:
  • 数学加法
  • 字符串连贯

当字符串是 + 运算符的操作数时,Javascript 不是将字符串转换为数字,而是将数字转换为字符串。

// concatenation
1 + "2" // "12"
1 + "js" // "1js"

// addition
1 + 2 // 3
1 + 2 + 1 // 4

//addition, then concatenation
1 + 2 + "1" // "31"
(1 + 2) + "1" // "31"

//concatenation all through
1 + "2" + 1 // "121"
(1 + "2") + 1 // "121"

对象

大多数 Javascript 对象转换通常会导致[object Object],例如

"name" + {} // "name[object Object]

每个 javascript 对象都继承了一个 toString 办法,每当将对象转换为字符串时都会调用该办法。该 toString 办法的返回值用于字符串连贯和数学表达式等操作。

const foo = {}
foo.toString() // [object Object]

const baz = {toString: () => "I'm object baz"
}

baz + "!" // "I'm object baz!"

当它是数学表达式时,Javascript 将尝试将返回值转换为数字,如果不是。

const foo = {toString: () => 4
}

2 * foo // 8
2 / foo // 0.5
2 + foo // 6
"four" + foo // "four4"

const baz = {toString: () => "four"
}

2 * baz // NaN
2 + baz // 2four

const bar = {toString: () => "2"
}

2 + bar // "22"
2 * bar // 4

数组对象

toStringArrays 的继承办法有点不同,它的工作形式相似于 join 不带任何参数调用数组的办法。

[1,2,3].toString() // "1,2,3"
[1,2,3].join() // "1,2,3"
[].toString() // ""[].join() //""

"me" + [1,2,3] // "me1,2,3"
4 + [1,2,3] // "41,2,3"
4 * [1,2,3] // NaN

因而,当您在须要字符串的中央传递数组时,Javascript 会将 toString 办法的返回值与第二个操作数连接起来。如果它须要一个数字,它会尝试将返回值转换为一个数字。

4 * [] // 0
4 / [2] // 2

//similar to
4 * Number([].toString())
4 * Number("")
4 * 0

//

4 / Number([2].toString())
4 / Number("2")
4 / 2

真、假和“”

Number(true) // 1
Number(false) // 0
Number("") // 0

4 + true // 5
3 * false // 0
3 * "" // 0
3 + ""//"3"

参考视频解说:进入学习

valueOf 办法

也能够定义一个 valueOf 办法,当您传递一个须要字符串或数字值的对象时,Javascript 将应用该办法。

const foo = {valueOf: () => 3
}

3 + foo // 6
3 * foo // 9

当对象上同时定义了 toStringvalueOf办法时,Javascript 将应用该 valueOf 办法。

const bar = {toString: () => 2,
  valueOf: () => 5}

"sa" + bar // "sa5"
3 * bar // 15
2 + bar // 7

valueOf 办法实用于应该示意数值的对象。

const two = new Number(2)

two.valueOf() // 2

虚伪与实在

我真的想让它变得虚伪和实在

每个 Javascript 值都能够被强制为 true 或 false。强制转换为布尔值 true 意味着该值是实在的。强制转换为布尔值 false 意味着该值为假。

Javascript 中有一些返回假值的值,它们是:

  1. 谬误的
  2. 0
  3. 空值
  4. 不明确的
  5. “”
  6. NaN
  7. -0

其余的都是真的

if (-1) // truthy
if ("0") // truthy
if ({}) // truthy

下面的代码片段是能够的,然而在尝试确定值的真实性时,最好是明确的。基本上,不要依赖 Javascript 的隐式强制,即便您感觉本人十分理解它们。
而不是上面的代码片段,

const counter = 2

if (counter)

依据您的要求,以下任何一种都是更好的做法

if (counter === 2)

//or

if (typeof counter === "number")

这是因为例如,您定义了一个应该解决数字的函数

const add = (number) => {if (!number) new Error("Only accepts arguments of type: number")
  //your code
}

所以如果我用 0 调用 add 函数,我总是会失去一个意想不到的谬误

add(0) // Error: Only accepts arguments of type: number

//better check

const add = (number) => {if (typeof number !== "number") new Error("Only accepts arguments of type: number")
  //your code
}

add(0) // no error

NaN

NaN 是一个不等于本身的非凡数值。

NaN === NaN // false

const notANumber = 3 * "a" // NaN

notANumber == notANumber // false
notANumber === notANumber // false

NaN是惟一不等于本身的 Javascript 值。因而,您能够 NaN 通过将其与本身进行比拟来查看。

if (notANumber !== notANumber) // true

ECMAScript 6 引入了一种查看 NaN 的办法,Number.isNaN

Number.isNaN(NaN) // true
Number.isNaN("name") // false

当心全局 isNaN 函数,它会在查看它是否为NaN. 例如,

isNaN("name") // true
isNaN("1") // false

isNaN应该防止应用全局函数,它的工作形式相似于上面的函数

const coerceThenCheckNaN = (val) => {const coercedVal = Number(val)
  return coercedVal !== coercedVal ? true : false
}

coerceThenCheckNaN("1a") // true
coerceThenCheckNaN("1") // false
coerceThenCheckNaN("as") // true
coerceThenCheckNaN(NaN) // true
coerceThenCheckNaN(10) // false

这是大部分隐性强制。如果我错过了什么,请在上面的评论中退出,感谢您一路浏览。

正文完
 0