通过引用传递字符串作为参数
Posted
技术标签:
【中文标题】通过引用传递字符串作为参数【英文标题】: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 总是按值传递。 制作方法并返回新值?没有真正的神奇解决方案。 一旦你返回新的字符串,你总是可以将原始字符串的内容设置为你的函数返回的字符串 【参考方案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 || '|')
;
【讨论】:
以上是关于通过引用传递字符串作为参数的主要内容,如果未能解决你的问题,请参考以下文章