Javascript 的隐式强制只是指 Javascript 试图将意外的值类型强制为预期的类型。因而,您能够在须要数字的中央传递一个字符串,在须要字符串的中央传递一个对象等,它会尝试将其转换为正确的类型。这是最好防止的 Javascript 性能。
3 * "3" //91 + "2" + 1 //121true + true //210 - true //9const foo = { valueOf: () => 2}3 + foo // 54 * foo // 8const bar = { toString: () => " promise is a boy :)"}1 + bar // "1 promise is a boy :)"4 * [] // 04 * [2] // 84 + [2] // "42"4 + [1, 2] // "41,2"4 * [1, 2] // NaN"string" ? 4 : 1 // 4undefined ? 4 : 1 // 1
数字表达式中的非数字值
字符串
每当您在波及以下任一运算符的数字表达式中将字符串作为操作数传递时:-, *, /, %
,数字的转换过程相似于对值调用内置Number
函数。这非常简单,任何仅蕴含数字字符的字符串都将转换为其等效的数字,但蕴含非数字字符的字符串将返回NaN
. 如下图,
3 * "3" // 3 * 33 * Number("3") // 3 * 3Number("5") // 5Number("1.") // 1Number("1.34") // 1.34Number("0") // 0Number("012") // 12Number("1,") // NaNNumber("1+1") // NaNNumber("1a") // NaNNumber("one") // NaNNumber("text") // NaN
+ 运算符的状况
- 运算符与其余数学运算符不同,执行两个性能:
- 数学加法
- 字符串连贯
当字符串是 + 运算符的操作数时,Javascript 不是将字符串转换为数字,而是将数字转换为字符串。
// concatenation1 + "2" // "12"1 + "js" // "1js"// addition1 + 2 // 31 + 2 + 1 // 4//addition, then concatenation1 + 2 + "1" // "31"(1 + 2) + "1" // "31"//concatenation all through1 + "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 // 82 / foo // 0.52 + foo // 6"four" + foo // "four4"const baz = { toString: () => "four"}2 * baz // NaN2 + baz // 2fourconst bar = { toString: () => "2"}2 + bar // "22"2 * bar // 4
数组对象
toString
Arrays的继承办法有点不同,它的工作形式相似于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 * [] // 04 / [2] // 2//similar to4 * Number([].toString())4 * Number("")4 * 0//4 / Number([2].toString())4 / Number("2")4 / 2
真、假和“”
Number(true) // 1Number(false) // 0Number("") // 04 + true // 53 * false // 03 * "" // 03 + "" // "3"
该valueOf
办法
也能够定义一个valueOf
办法,当您传递一个须要字符串或数字值的对象时,Javascript 将应用该办法。
const foo = { valueOf: () => 3}3 + foo // 63 * foo // 9
当对象上同时定义了toString
和valueOf
办法时,Javascript 将应用该valueOf
办法。
const bar = { toString: () => 2, valueOf: () => 5}"sa" + bar // "sa5"3 * bar // 152 + bar // 7
valueOf 办法实用于应该示意数值的对象。
const two = new Number(2)two.valueOf() // 2
虚伪与实在
我真的想让它变得虚伪和实在
每个 Javascript 值都能够被强制为 true 或 false。强制转换为布尔值true
意味着该值是实在的。强制转换为布尔值false
意味着该值为假。
Javascript 中有一些返回假值的值,它们是:
- 谬误的
- 0
- 空值
- 不明确的
- “”
- NaN
- -0
其余的都是真的
if (-1) // truthyif ("0") // truthyif ({}) // truthy
下面的代码片段是能够的,然而在尝试确定值的真实性时,最好是明确的。基本上,不要依赖 Javascript 的隐式强制,即便您感觉本人十分理解它们。
而不是上面的代码片段,
const counter = 2if (counter)
依据您的要求,以下任何一种都是更好的做法
if (counter === 2)//orif (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 checkconst add = (number) => { if (typeof number !== "number") new Error("Only accepts arguments of type: number") //your code}add(0) // no error
NaN
NaN
是一个不等于本身的非凡数值。
NaN === NaN // falseconst notANumber = 3 * "a" // NaNnotANumber == notANumber // falsenotANumber === notANumber // false
NaN
是惟一不等于本身的 Javascript 值。因而,您能够NaN
通过将其与本身进行比拟来查看。
if (notANumber !== notANumber) // true
ECMAScript 6 引入了一种查看 NaN 的办法, Number.isNaN
Number.isNaN(NaN) // trueNumber.isNaN("name") // false
当心全局isNaN
函数,它会在查看它是否为NaN
. 例如,
isNaN("name") // trueisNaN("1") // false
isNaN
应该防止应用全局函数,它的工作形式相似于上面的函数
const coerceThenCheckNaN = (val) => { const coercedVal = Number(val) return coercedVal !== coercedVal ? true : false}coerceThenCheckNaN("1a") // truecoerceThenCheckNaN("1") // falsecoerceThenCheckNaN("as") // truecoerceThenCheckNaN(NaN) // truecoerceThenCheckNaN(10) // false
这是大部分隐性强制。如果我错过了什么,请在上面的评论中退出,感谢您一路浏览。