博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[]为false,!![]为true,[true] == 'true'为true,傻傻分不清
阅读量:6693 次
发布时间:2019-06-25

本文共 3592 字,大约阅读时间需要 11 分钟。

先看看官方对于隐式转换的定义

注意图片中的第7条:If Type(y) is Boolean, return the result of the comparison x == ToNumber(y). 第9条:If Type(x) is Object and Type(y) is either String or Number,return the result of the comparison ToPrimitive(x) == y.

那么我们以[] == false为例,先对x进行ToPrimitive(x),在对y进行ToNumber(y).

这里我们先来了解一下ToPrimitive()和ToNumber()的源码

ToPrimitive和ToNumber

ToPrimitive

// ECMA-262, section 9.1, page 30. Use null/undefined for no hint,// (1) for number hint, and (2) for string hint.function ToPrimitive(x, hint) {    // Fast case check.  if (IS_STRING(x)) return x;  // Normal behavior.  if (!IS_SPEC_OBJECT(x)) return x;  if (IS_SYMBOL_WRAPPER(x)) throw MakeTypeError(kSymbolToPrimitive);  if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;  return (hint == NUMBER_HINT) ? DefaultNumber(x) : DefaultString(x);}// ECMA-262, section 8.6.2.6, page 28.function DefaultNumber(x) {    if (!IS_SYMBOL_WRAPPER(x)) {    var valueOf = x.valueOf;    if (IS_SPEC_FUNCTION(valueOf)) {      var v = %_CallFunction(x, valueOf);      if (IsPrimitive(v)) return v;    }    var toString = x.toString;    if (IS_SPEC_FUNCTION(toString)) {      var s = %_CallFunction(x, toString);      if (IsPrimitive(s)) return s;    }  }  throw MakeTypeError(kCannotConvertToPrimitive);}// ECMA-262, section 8.6.2.6, page 28.function DefaultString(x) {    if (!IS_SYMBOL_WRAPPER(x)) {    var toString = x.toString;    if (IS_SPEC_FUNCTION(toString)) {      var s = %_CallFunction(x, toString);      if (IsPrimitive(s)) return s;    }    var valueOf = x.valueOf;    if (IS_SPEC_FUNCTION(valueOf)) {      var v = %_CallFunction(x, valueOf);      if (IsPrimitive(v)) return v;    }  }  throw MakeTypeError(kCannotConvertToPrimitive);}复制代码

大致的代码逻辑是:

  • 如果变量为字符串,直接返回
  • 如果!IS_SPEC_OBJECT(x),直接返回
  • 如果IS_SYMBOL_WRAPPER(x),则抛出异常
  • 否则会根据传入的hint来调用DefaultNumber和DefaultString,比如如果为Date对象,会调用DefaultString
    • DefaultNumber:首先x.valueOf,如果为primitive,则返回valueOf后的值,否则继续调用x.toString,如果为primitive,则返回toString后的值,否则抛出异常
    • DefaultString:和DefaultNumber正好相反,先调用toString,如果不是primitive再调用valueOf

ToNumber

// ECMA-262, section 9.3, page 31.function ToNumber(x) {    if (IS_NUMBER(x)) return x;  // 字符串转数字调用StringToNumber  if (IS_STRING(x)) {    return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x) : %StringToNumber(x);  }  // 布尔型转数字时true返回1,false返回0  if (IS_BOOLEAN(x)) return x ? 1 : 0;  // undefined返回NAN  if (IS_UNDEFINED(x)) return NAN;  // Symbol抛出异常,例如:Symbol() + 1  if (IS_SYMBOL(x)) throw MakeTypeError(kSymbolToNumber);  return (IS_NULL(x)) ? 0 : ToNumber(DefaultNumber(x));}复制代码

ToString

// ECMA-262, section 9.8, page 35.function ToString(x) {    if (IS_STRING(x)) return x;  // 数字转字符串,调用内部的_NumberToString  if (IS_NUMBER(x)) return %_NumberToString(x);  // 布尔型转字符串,true返回字符串true  if (IS_BOOLEAN(x)) return x ? 'true' : 'false';  // undefined转字符串,返回undefined  if (IS_UNDEFINED(x)) return 'undefined';  // Symbol抛出异常  if (IS_SYMBOL(x)) throw MakeTypeError(kSymbolToString);  return (IS_NULL(x)) ? 'null' : ToString(DefaultString(x));}复制代码

那么[].valueOf()的结果是[],在对[]调用toString的方法,得到的结果是""。 而true调用ToNumber的方法得到的结果是1。 "" == 1 返回的是false,所以[] == true,返回false。

那么我们再来看看!![] == true是怎么解读的? 根据优先级,先进行!操作。

所以!![]相当于!!(ToBoolean([]))

ToBoolean源码

// ECMA-262, section 9.2, page 30function ToBoolean(x) {    if (IS_BOOLEAN(x)) return x;  // 字符串转布尔型时,如果length不为0就返回true  if (IS_STRING(x)) return x.length != 0;  if (x == null) return false;  // 数字转布尔型时,变量不为0或NAN时返回true  if (IS_NUMBER(x)) return !((x == 0) || NUMBER_IS_NAN(x));  return true;}复制代码

从源码中,我们得知,null,undefined,0,"",false,NaN,返回false。其余都是返回true。

那么!![],转换之后等于!!true,即true。

那其余的一个就留给大家自己分析啦!!!

转载地址:http://kecoo.baihongyu.com/

你可能感兴趣的文章
JAVA面向对象编程深入理解图
查看>>
jsp与jsp之间传参数如何获取
查看>>
如何做好一名售前工程师 [理论]
查看>>
什么是语法糖?
查看>>
rabbitMQ的安装和创建用户
查看>>
Struts2笔记——第一个实例HelloWorld
查看>>
Maven安装
查看>>
2.1列表相关知识点
查看>>
OpenStack images
查看>>
xsigo systems
查看>>
ofbiz ins
查看>>
iOS动画实现改变frme和contenOffset
查看>>
DroidPilot使用第一步 - 安装
查看>>
vue-cli —— 项目打包及一些注意事项
查看>>
1.1 变量
查看>>
mfc 链接时错误 文件函数重复定义
查看>>
php
查看>>
Django 是如何实现用户登录和登出机制的(默认版本-数据库版本)
查看>>
【转】 wpf系列-入门
查看>>
exp6
查看>>