- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
JavaScript这门语言的类型系统从来没有它表面看起来的那样和善,虽然比起Java、C#等一众强类型语言,它的弱类型使用起来似乎是如此便利,但正因为它极高的自由度,所以才会衍生出令人摸不着头脑的荒诞行为。 举个例子,虽然我们都知道一个包含内容的字符串会被认为是“真值 Truthy”(因为除了空字符串之外任何字符串在JS里都被认为真值),但当你做如下比较的时候,你会得到一个惊掉下巴的结果 。
const a = "18";
const b = true;
a == b // false
什么鬼,一个被通常理解成真值的值,竟然无法与布尔真值松散相等? 为了能拨开JavaScript类型的迷雾,让头铁的我们一点一点理顺JavaScript整个类型系统的工作逻辑.
读者可以根据自己对JS类型系统的掌握程度,选择性的阅读这篇博客 。
JavaScript有以下八大类型,除了object类型,其他都为基本类型 。
number
string
boolean
null
undefined
object
symbol
bigint
他们的类型都可以直接被typeof识别,特例是 。
typeof null
为"object"
虽然它是null
类型的值typeof function(){}
为"function"
虽然它理论上是object
类型的虽然你可能已经为这种特例所不解,但其实这才刚开始,大的还在后面 。
JavaScript内部有一套抽象的数字转换机制叫ToNumber,这套机制在隐式转换或者部分显式转换其他类型值到数字时会被调用。虽然你可能会被恶心到,但我还是要向你介绍这套机制的规则为 。
string
若为数字表达式则转换为其对应数字,否则返回NaN
undefined
转换为NaN
null
转换为0
true
转换为数字1
false
转换为数字0
object
类型会依次调用toPrimitive()
、valueOf()
和toString()
来获取值,并利用上面的规则获取其数字值ToNumber的转换规则会在以下情况下使用,当然这些情况也可以称作转换数字的“技巧”,看你怎么理解它了:
Number(value)
+ value
Math.floor(value)
value * x
,将一个值做乘法运算没错,Math.floor(true)、+ true、true * 1都等于1,是不是觉得很荒诞?
但'5' + 3或者5 + '3'结果都是字符串'53',因为+在有两个操作值,且其中一个为字符串时,会直接做字符串拼接。所以虽然+ '3'结果为数字3,但5 + '3'的结果不是8 。
parseInt()或parseFloat()只接受string类型,所以转换规则与ToNumber转换机制下的string类型情况相似,但是在处理字符时采取从左到右的扫描直到失败为止的方法,所以parseInt("123hello")结果为123 。
JavaScript还有一套针对布尔类型的抽象转换机制叫ToBoolean。因为对于前端逻辑编写来讲,判断一个值是否为真实在太重要了,JavaScript里变量像薛定谔的猫一样,处于存在与不存在、真和假的中间态,所以我们JS开发者都有一个奇怪的脑回路,当看到一个字面量值的时候就开始评估它是“真值”(Trusy Value)还是“假值”(Falsy Value)。 可是,与物理学里薛定谔的猫现象相反,JavaScript里对真假值的定义其实很简单,以下的值均为假值:
undefined
null
false
+0
、-0
、0n
和NaN
""
其他均为真值,任何非空字符串、非0数字、对象都是真值.
转换其他类型值为布尔类型的方法:
!!value
Boolean(value)
!
,可将值转换为布尔类型,但是真假结果相反会隐式的将其他类型值转换为布尔的情况:
&&
||
if (value)
while (value)
for (...; value; ...)
,for循环的第二个测试表达式? :
,三元操作符恭喜你勇士,读到这里就代表马上你就能知道为什么"18" != true了!!! 。
我们都知道,JS当中有松散判断的弱等价==,和严格判断的强等价===两种判断等价方式。强等价要求两个操作值必须为同一类型,且值本身也相等,其行为非常容易预测。弱等价在比较值是否相等前会尝试做一些类型转换,尽可能的让可能为不同类型的两个值变得可以判断。 造成文章开头神奇判断结果的原因就在弱等价==时的类型转换策略上,听我将弱等价的转换规则为你娓娓道来 。
null
与undefined
松散比较结果相等toPrimitive()
获取原始类型值后进行比较所以,"18" == true进行比较时 。
ToNumber(true)
结果为数字1
,表达式变为"18" == 1
ToNumber("18")
结果为数字18
18 == 1
,结果为假false
所以没错,以下表达式均为真:"1" == true,"0" == false,false == "" 。
了解这个例子后你可能会对JavaScript语言行为设计混乱表达不满,但是上述边界条件可以通过引入TypeScript,避免弱等价判断转而使用严格等价,在隐式类型转换之前使用可预测行为的转换方法对值提前进行处理。 如果你无法采用上面列举的解决办法,那我的建议就是多多关注我的博客,如果觉得不错可以推荐给你的朋友或同事,说不定就能在身边慢慢带动大家采用更令人舒心的写法嘞.
ps. 辛苦读者了,为大家的好奇心与耐心致敬.
最后此篇关于神奇的JavaScript弱等价类型转换的文章就讲到这里了,如果你想了解更多关于神奇的JavaScript弱等价类型转换的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在尝试编写一个相当多态的库。我遇到了一种更容易表现出来却很难说出来的情况。它看起来有点像这样: {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE
谁能解释一下这个表达式是如何工作的? type = type || 'any'; 这是否意味着如果类型未定义则使用“任意”? 最佳答案 如果 type 为“falsy”(即 false,或 undef
我有一个界面,在IAnimal.fs中, namespace Kingdom type IAnimal = abstract member Eat : Food -> unit 以及另一个成功
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: What is the difference between (type)value and type(va
在 C# 中,default(Nullable) 之间有区别吗? (或 default(long?) )和 default(long) ? Long只是一个例子,它可以是任何其他struct类型。 最
假设我有一个案例类: case class Foo(num: Int, str: String, bool: Boolean) 现在我还有一个简单的包装器: sealed trait Wrapper[
这个问题在这里已经有了答案: Create C# delegate type with ref parameter at runtime (1 个回答) 关闭 2 年前。 为了即时创建委托(dele
我正在尝试获取图像的 dct。一开始我遇到了错误 The function/feature is not implemented (Odd-size DCT's are not implemented
我正在尝试使用 AFNetworking 的 AFPropertyListRequestOperation,但是当我尝试下载它时,出现错误 预期的内容类型{( “应用程序/x-plist” )}, 得
我在下面收到错误。我知道这段代码的意思,但我不知道界面应该是什么样子: Element implicitly has an 'any' type because index expression is
我尝试将 SignalType 从 ReactiveCocoa 扩展为自定义 ErrorType,代码如下所示 enum MyError: ErrorType { // .. cases }
我无法在任何其他问题中找到答案。假设我有一个抽象父类(super class) Abstract0,它有两个子类 Concrete1 和 Concrete1。我希望能够在 Abstract0 中定义类
我想知道为什么这个索引没有用在 RANGE 类型中,而是用在 INDEX 中: 索引: CREATE INDEX myindex ON orders(order_date); 查询: EXPLAIN
我正在使用 RxJava,现在我尝试通过提供 lambda 来订阅可观察对象: observableProvider.stringForKey(CURRENT_DELETED_ID) .sub
我已经尝试了几乎所有解决问题的方法,其中包括。为 提供类型使用app.use(express.static('public'))还有更多,但我似乎无法为此找到解决方案。 index.js : imp
以下哪个 CSS 选择器更快? input[type="submit"] { /* styles */ } 或 [type="submit"] { /* styles */ } 只是好
我不知道这个设置有什么问题,我在 IDEA 中获得了所有注释(@Controller、@Repository、@Service),它在行号左侧显示 bean,然后转到该 bean。 这是错误: 14-
我听从了建议 registering java function as a callback in C function并且可以使用“简单”类型(例如整数和字符串)进行回调,例如: jstring j
有一些 java 类,加载到 Oracle 数据库(版本 11g)和 pl/sql 函数包装器: create or replace function getDataFromJava( in_uLis
我已经从 David Walsh 的 css 动画回调中获取代码并将其修改为 TypeScript。但是,我收到一个错误,我不知道为什么: interface IBrowserPrefix { [
我是一名优秀的程序员,十分优秀!