【问题标题】:Passing string as parameter by reference通过引用传递字符串作为参数
【发布时间】:2018-08-13 10:48:49
【问题描述】:

我想改变函数中字符串的内容,例如

function appendSeparating(s, s2, separator) {
    if (s != "")
        s += separator;
    s += s2;
}

我想在返回时更改 s,但由于字符串是一个原始值,因此按值传递,因此修改不会影响原始值。

解决这个问题的最有效/最干净的方法是什么? (我尽量保持代码简洁)

【问题讨论】:

  • 您可以让函数返回新字符串。 JavaScript 总是按值传递。
  • 制作方法并返回新值?没有真正的神奇解决方案。
  • 一旦你返回新的字符串,你总是可以将原始字符串的内容设置为你的函数返回的字符串

标签: javascript string pass-by-reference


【解决方案1】:

如果这就是您的意思,JavaScript 没有 out 参数。处理这个问题的最简单方法是在对象中传递字符串。

function appendSeparating(stringObj, s2, separator) {
    if (stringObj.text != "")
        stringObj.text += separator;
    stringObj.text += s2;
}

【讨论】:

    【解决方案2】:

    你可以返回新的字符串。

    function appendSeparating(s, s2, separator) {
        s += s && separator;
        return s + s2;
    }
    
    var x = '';
    
    console.log(x = appendSeparating(x, 'one', ', '));
    console.log(x = appendSeparating(x, 'two', ', '));
    console.log(x = appendSeparating(x, 'three', ', '));

    使用对象,您可以获取对象、分离的键和其他部分并更新此属性。

    function appendSeparating(object, key, s2, separator) {
        object[key] += object[key] && separator;
        return object[key] += s2;
    }
    
    appendSeparating(clients[index].address, 'postalCode', 'foo', ', ');
    

    【讨论】:

    • 是的,但是让我烦恼的是一些复杂的语句,例如 clients[index].address.postalCode=appendSeparating(clients[index].address.postalCode,"whatever",",")。 (必须重复字符串语句会触发我的懒惰,我觉得它太乱了:-)
    • 在这种情况下,您有一个对象引用,您可以通过分离对象和键来处理它,并执行您需要的操作并更新对象并返回实际值。
    【解决方案3】:

    here 提出了类似的问题,答案包括实现替代方案。

    长话短说:将你想“通过引用传递”的字符串包装在一个对象中,然后修改该对象,如this fiddle所示

    function concatStrings(stringObj, s2, separator) {
        stringObj.value = stringObj.value + separator + s2;
    }
    
    var baseString = "hello";
    var stringObj = {value: baseString};
    var s2 = "world";
    var separator = " ";
    
    concatStrings(stringObj, s2, separator);
    
    window.alert(stringObj.value);
    

    【讨论】:

      【解决方案4】:

      全局变量

      虽然字符串原语不是通过引用传递的,但没有提到的一个选项是使用全局变量的能力。凭我自己的良心,我必须建议不要这样做,但不知道你的用例你应该知道你的选择:

      s = 'a'                       // created as a global variable
      appendSeparating('b', '|')    // function now takes only two arguments
      console.log(s)                // global variable affected
      
      function appendSeparating(s2, separator) {
        // s is a global variable
        if (typeof s === 'undefined')
          return;
      
        if (s != "")
          s += separator;
        s += s2;
      }

      返回作业

      当然,您可以构建自己的函数并将返回变量用作赋值。下面我使用了一个原型函数,但也应该建议不要这样做,没有完全理解其含义(经验可能需要数年)——你可能会看到我在教你什么不该做:

      String.prototype.append = function(str, delimiter) {
        return [this, str].filter(v => v !== '').join(delimiter || '|')
      };
      
      
      let ex1 = 'a'
      ex1 = ex1.append('b')
      console.log('no delim: ', ex1)
      
      
      let ex2 = 'a'
      ex2 = ex2.append('b', '-')
      console.log('w/ delim: ', ex2)

      这里有一个“更好”的方法来做同样的事情。尽管效率很高,但未经训练的眼睛可能很难理解函数体中发生了什么。这是主观的,但为了可维护性,您可能希望使某些内容更具可读性:

      let ex1 = 'a'
      ex1 = append(ex1, 'b')
      console.log('no delim: ', ex1)
      
      
      let ex2 = 'a'
      ex2 = append(ex2, 'b', '-')
      console.log('w/ delim: ', ex2)
      
      
      function append(prefix, suffix, delimiter) {
        return [prefix, suffix].filter(v => v !== '').join(delimiter || '|')
      };

      对象变异/作用域

      您可以做的最后一件事是修改一个对象。这不仅会接近您想要的效果,而且在较大的应用程序中,对象中的变量范围非常好,以避免冲突并简化调试(但以性能损失为代价):

      const strings = {}
      
      // Assuming key name
      strings.s = 'foo'
      append(strings, 'bar', ': ')
      console.log(strings.s)
      
      // Supplying key name
      strings.x = 'x'
      appendNamed(strings, 'x', 'y')
      console.log(strings.x)
      
      
      
      function append(str, suffix, delimiter) {
        str.s = [str.s, suffix].filter(v => v !== '').join(delimiter || '|')
      };
      
      function appendNamed(str, strName, suffix, delimiter){
        str[strName] = [str[strName], suffix].filter(v => v !== '').join(delimiter || '|')
      };

      【讨论】:

        猜你喜欢
        • 2016-10-26
        • 1970-01-01
        • 2014-02-03
        • 2018-09-01
        • 2014-08-11
        • 2017-07-25
        • 2016-07-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多