通过引用传递字符串作为参数

Passing string as parameter by reference

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

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

我想对 return 进行修改,但由于字符串是按值传递的原语,因此修改不会影响原始字符串。

最efficient/clean处理这个问题的方法是什么? (我尽量保持代码简洁)

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

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

您可以 return 新字符串。

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', ', ');

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

长话短说:将你想要"pass by reference"的字符串包裹在一个对象中,然后修改对象,如图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);

全局变量

虽然字符串基元不是通过引用传递的,但未提及的一个选项是使用全局变量的能力。凭我自己的良心,我必须反对这样做,但不知道你的用例你应该知道你的选择:

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;
}


Return 作业

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

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)

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

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 || '|')
};