具有null或未定义值的JavaScript字符串连接行为

 冬季梅花1991_156 发布于 2023-02-10 22:22

您可能知道,在JavaScript '' + null = "null"'' + undefined = "undefined"(在大多数浏览器中我可以测试:Firefox,Chrome和IE).我想知道这种奇怪的起源(Brendan Eich头脑中究竟是什么?!)以及是否有任何改变ECMA未来版本的目标.确实非常令人沮丧的是,必须要将'sthg' + (var || '')Strings与变量连接起来并使用像Underscore或其他的第三方框架那样使用锤子进行果冻钉敲击.

编辑:

为了满足StackOverflow所要求的标准并澄清我的问题,它有三个:

在串联中使JS转换null或其undefined字符串值的奇怪背后的历史是什么String

在将来的ECMAScript版本中是否有机会改变这种行为?

什么是连接最漂亮的方式String与潜在nullundefined对象不落入这个问题(得到一些"undefined""null"在字符串的中间)?根据主观标准最漂亮,我的意思是:简短,干净,有效.没必要说那'' + (obj ? obj : '')不是很漂亮......

Oriol.. 73

您可以使用Array.prototype.join忽略undefinednull:

['a', 'b', void 0, null, 6].join(''); // 'ab6'

根据规格:

如果elementundefinednull,则接下来是空字符串; 否则,让接下来是ToString(元素).


鉴于,

在串联中使JS转换null或其undefined字符串值的奇怪背后的历史是什么String

事实上,在某些情况下,当前的行为是有道理的.

function showSum(a,b) {
    alert(a + ' + ' + b + ' = ' + (+a + +b));
}

例如,如果上面的函数是在没有参数的情况下调用的,那么undefined + undefined = NaN可能比 + = NaN.

一般来说,我认为如果你想在字符串中插入一些变量,显示undefinednull有意义.可能,Eich也这么认为.

当然,有些情况下忽略那些会更好,例如将字符串连接在一起时.但对于那些你可以使用的情况Array.prototype.join.

在将来的ECMAScript版本中是否有机会改变这种行为?

很可能不是.

既然已经存在Array.prototype.join,修改字符串连接的行为只会导致缺点,但没有优势.而且,它会破坏旧代码,因此它不会向后兼容.

连接字符串与潜在null或最有效的方法是什么undefined

Array.prototype.join似乎是最简单的一个.它是否最漂亮可能是基于意见的.

*"你可以使用Array.prototype.join忽略undefined和null"* - 值得注意的是,如果你使用空字符串作为你的`join` arg,这只能按照你的需要工作. (11认同)


Ingo Bürk.. 30

什么是将String与潜在的null或未定义的对象连接起来的最漂亮的方法,而不会陷入这个问题[...]?

有几种方法,你自己部分提到它们.简而言之,我能想到的唯一干净的方法是功能:

const Strings = {};
Strings.orEmpty = function( entity ) {
    return entity || "";
};

// usage
const message = "This is a " + Strings.orEmpty( test );

当然,您可以(并且应该)更改实际实施以满足您的需求.这就是我认为这种方法优越的原因:它引入了封装.

真的,如果你没有封装,你只需要询问"最漂亮"的方式.你问自己这个问题,因为你已经知道自己会进入一个你无法改变实现的地方,所以你希望它能够立刻完美.但事情就是这样:需求,观点甚至环境都会发生变化.他们进化了.那么为什么不让自己改变实现只需要调整一行,也许一两次测试?

你可以称之为作弊,因为它并没有真正回答如何实现实际的逻辑.但这是我的观点:没关系.好吧,也许一点点.但实际上,没有必要担心,因为改变是多么简单.而且由于它没有内联,它看起来也更漂亮 - 无论你是以这种方式还是以更复杂的方式实现它.

如果在整个代码中,您不断重复||内联,则会遇到两个问题:

你重复代码.

而且由于您复制了代码,因此将来很难进行维护和更改.

在高质量的软件开发方面,这些通常被认为是反模式的两点.

有人会说这太开销了; 他们会谈论表现.这是无意义的.首先,这几乎不会增加开销.如果这是你担心的,你选择了错误的语言.甚至jQuery也使用函数.人们需要克服微观优化.

另一件事是:你可以使用代码"compiler"= minifier.此区域中的好工具将尝试在编译步骤中检测要内联的语句.这样,您可以保持代码的清洁和可维护性,如果您仍然相信它或者确实有一个重要的环境,那么仍然可以获得最后一滴性能.

最后,对浏览器有一定的信心.他们将优化代码,这些天他们做得非常好.

3 个回答
  • 您可以使用Array.prototype.join忽略undefinednull:

    ['a', 'b', void 0, null, 6].join(''); // 'ab6'
    

    根据规格:

    如果elementundefinednull,则接下来是空字符串; 否则,让接下来是ToString(元素).


    鉴于,

    在串联中使JS转换null或其undefined字符串值的奇怪背后的历史是什么String

    事实上,在某些情况下,当前的行为是有道理的.

    function showSum(a,b) {
        alert(a + ' + ' + b + ' = ' + (+a + +b));
    }

    例如,如果上面的函数是在没有参数的情况下调用的,那么undefined + undefined = NaN可能比 + = NaN.

    一般来说,我认为如果你想在字符串中插入一些变量,显示undefinednull有意义.可能,Eich也这么认为.

    当然,有些情况下忽略那些会更好,例如将字符串连接在一起时.但对于那些你可以使用的情况Array.prototype.join.

    在将来的ECMAScript版本中是否有机会改变这种行为?

    很可能不是.

    既然已经存在Array.prototype.join,修改字符串连接的行为只会导致缺点,但没有优势.而且,它会破坏旧代码,因此它不会向后兼容.

    连接字符串与潜在null或最有效的方法是什么undefined

    Array.prototype.join似乎是最简单的一个.它是否最漂亮可能是基于意见的.

    2023-02-10 22:30 回答
  • 什么是将String与潜在的null或未定义的对象连接起来的最漂亮的方法,而不会陷入这个问题[...]?

    有几种方法,你自己部分提到它们.简而言之,我能想到的唯一干净的方法是功能:

    const Strings = {};
    Strings.orEmpty = function( entity ) {
        return entity || "";
    };
    
    // usage
    const message = "This is a " + Strings.orEmpty( test );
    

    当然,您可以(并且应该)更改实际实施以满足您的需求.这就是我认为这种方法优越的原因:它引入了封装.

    真的,如果你没有封装,你只需要询问"最漂亮"的方式.你问自己这个问题,因为你已经知道自己会进入一个你无法改变实现的地方,所以你希望它能够立刻完美.但事情就是这样:需求,观点甚至环境都会发生变化.他们进化了.那么为什么不让自己改变实现只需要调整一行,也许一两次测试?

    你可以称之为作弊,因为它并没有真正回答如何实现实际的逻辑.但这是我的观点:没关系.好吧,也许一点点.但实际上,没有必要担心,因为改变是多么简单.而且由于它没有内联,它看起来也更漂亮 - 无论你是以这种方式还是以更复杂的方式实现它.

    如果在整个代码中,您不断重复||内联,则会遇到两个问题:

    你重复代码.

    而且由于您复制了代码,因此将来很难进行维护和更改.

    在高质量的软件开发方面,这些通常被认为是反模式的两点.

    有人会说这太开销了; 他们会谈论表现.这是无意义的.首先,这几乎不会增加开销.如果这是你担心的,你选择了错误的语言.甚至jQuery也使用函数.人们需要克服微观优化.

    另一件事是:你可以使用代码"compiler"= minifier.此区域中的好工具将尝试在编译步骤中检测要内联的语句.这样,您可以保持代码的清洁和可维护性,如果您仍然相信它或者确实有一个重要的环境,那么仍然可以获得最后一滴性能.

    最后,对浏览器有一定的信心.他们将优化代码,这些天他们做得非常好.

    2023-02-10 22:37 回答
  • ECMA规范

    只是为了充实它在规范方面表现如此的原因,这种行为自第一版开始就存在.那里和5.1中的定义在语义上是等价的,我将展示5.1定义.

    第11.6.1节:加法运算符(+)

    加法运算符执行字符串连接或数字加法.

    生产AdditiveExpression:AdditiveExpression + MultiplicativeExpression的计算方法如下:

      lref成为评估AdditiveExpression的结果.

      lval为GetValue(lref).

      rref是评估MultiplicativeExpression的结果.

      rval为GetValue(rref).

      lprim为ToPrimitive(lval).

      rprim为ToPrimitive(rval).

      如果Type(lprim)是String或Type(rprim)是String,那么
      a.返回串联ToString(lprim)后跟ToString(rprim)的结果的字符串

      将添加操作的结果返回到ToNumber(lprim)和ToNumber(rprim).见11.6.3下面的注释.

    因此,如果任一值最终为a String,则ToString在两个参数(第7行)上使用,并将它们连接起来(第7a行). ToPrimitive返回所有非对象值不变,因此null并且undefined不受影响:

    第9.1节ToPrimitive

    抽象操作ToPrimitive接受输入参数和可选参数PreferredType.抽象操作ToPrimitive将其输入参数转换为非Object类型...根据表10进行转换:

    对于所有非Object类型,包括两者NullUndefined,[t]he result equals the input argument (no conversion). 所以ToPrimitive在这里什么都不做.

    最后,第9.8节ToString

    抽象操作ToString根据表13将其参数转换为String类型的值:

    表13给出了"undefined"Undefined类型和"null"Null类型.

    它会改变吗?它甚至是"古怪"吗?

    正如其他人所指出的那样,这种情况不太可能发生变化,因为它会破坏向后兼容性(并没有带来真正的好处),甚至更多,因为这种行为与规范的1997版本相同.我也不会认为这很奇怪.

    如果你要改变这种行为,你会改变的定义ToStringnull,并undefined或将你的特殊情况下这些值的加法运算符? ToString在整个规范中使用了很多很多地方, "null"似乎是一个无可争议的代表选择null.举几个例子,在Java中"" + null是字符串"null",在Python中str(None)是字符串"None".

    解决方法

    其他人都给予很好的解决方法,但我想补充一点,我怀疑你想使用entity || ""作为自己的战略,因为它解析true"true",但false"".该阵列加入这个答案有更多的预期的行为,或者你可以改变的执行这个答案检查entity == null(包括null == nullundefined == null为真).

    2023-02-10 22:38 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有