javascript使用不可变字符串还是可变字符串?我需要一个“字符串生成器”吗?
JavaScript字符串确实是不可变的。
Javascript中的字符串是不可变的
从犀牛书:
在JavaScript中,字符串是不可变的对象,这意味着 其中的字符不能被改变,任何操作 字符串实际上会创建新的字符串。字符串由 引用,而不是通过值。通常,当对象被赋值时 引用,通过一个引用对对象所做的更改将为 通过对该对象的所有其他引用可见。因为字符串 属性的多个引用不能更改,但是可以对 字符串对象,不用担心字符串值会没有变化 你知道它
性能提示:
如果你必须连接大字符串,将字符串部分放入一个数组中,并使用Array.Join()方法来获取整个字符串。这对于连接大量字符串来说可以快很多倍。
Array.Join()
JavaScript中没有StringBuilder。
StringBuilder
关于你的问题(在你对Ash的回复的评论中)关于ASP中的StringBuilder。NET Ajax专家们似乎不同意这一点。
Christian Wenz在他的书编程ASP。净AJAX (O'Reilly)中说:“这种方法对内存没有任何可测量的影响(事实上,实现似乎比标准方法慢一点)。”
另一方面,Gallo等人在他们的书ASP。NET AJAX的应用 (Manning)中说:“当要连接的字符串数量更大时,字符串构建器成为避免巨大性能下降的基本对象。”
我猜您需要自己进行基准测试,不同浏览器的测试结果也可能不同。然而,即使它不能提高性能,对于习惯于用c#或Java等语言编写StringBuilders的程序员来说,它仍然被认为是“有用的”。
它们是不可变的。你不能用var myString = "abbdef"; myString[2] = 'c'之类的东西来改变字符串中的字符。字符串操作方法如trim, slice返回新字符串。
var myString = "abbdef"; myString[2] = 'c'
trim
slice
同样地,如果对同一个字符串有两个引用,修改其中一个不会影响另一个
let a = b = "hello"; a = a + " world"; // b is not affected
然而,我总是听到Ash在他的回答中提到的(使用Array。所以我想测试连接字符串的不同方法,并将最快的方法抽象到StringBuilder中。我写了一些测试来验证这是否正确(它不是!)。
我相信这是最快的方法,尽管我一直在想添加一个方法调用可能会使它变慢……
function StringBuilder() { this._array = []; this._index = 0; } StringBuilder.prototype.append = function (str) { this._array[this._index] = str; this._index++; } StringBuilder.prototype.toString = function () { return this._array.join(''); }
这里是性能速度测试。它们三个都创建了一个巨大的字符串,由"Hello diggity dog"连接10万次到一个空字符串组成。
"Hello diggity dog"
我创建了三种类型的测试
Array.push
Array.join
然后我通过将它们抽象为StringBuilderConcat, StringBuilderArrayPush和StringBuilderArrayIndex http://jsperf.com/string-concat-without-sringbuilder/5创建了相同的三个测试,请去那里运行测试,这样我们就可以得到一个很好的示例。请注意,我修复了一个小错误,因此测试数据被擦除,一旦有足够的性能数据,我将更新表。到http://jsperf.com/string-concat-without-sringbuilder/5找到旧的数据表。
StringBuilderConcat
StringBuilderArrayPush
StringBuilderArrayIndex
以下是一些数字(Ma5rch 2018最新更新),如果你不想关注链接。每次测试的数值为每秒1000次操作(越高越好)
发现
希望其他人会觉得这个有用
不同的测试用例
因为@RoyTinker认为我的测试是有缺陷的,我创建了一个新的情况下,不创建一个大字符串连接相同的字符串,它使用不同的字符为每次迭代。字符串连接似乎还是更快,或者一样快。让我们进行测试
我建议每个人都应该继续考虑其他测试方法,并在下面添加到不同测试用例的新链接。
http://jsperf.com/string-concat-without-sringbuilder/7
字符串是不可变的 -它们不能改变,我们只能创建新的字符串。
例子:
var str= "Immutable value"; // it is immutable var other= statement.slice(2, 10); // new string
字符串类型的值是不可变的,但 string对象是使用string()构造函数创建的,它是可变的,因为它是一个对象,你可以向它添加新的属性。
> var str = new String("test") undefined > str [String: 'test'] > str.newProp = "some value" 'some value' > str { [String: 'test'] newProp: 'some value' }
同时,虽然您可以添加新的属性,但不能更改已经存在的属性
Chrome控制台测试截图
这是一个很晚的帖子,但我没有在答案中找到一个好的书的引用。
这是一本可靠的书中明确的注释:
字符串在ECMAScript中是不可变的,这意味着一旦它们被创建,它们的值就不能改变。要改变由变量保存的字符串,必须销毁原始字符串,并用另一个包含新值的字符串填充变量… - Web开发人员的专业JavaScript,第3版,第43页
现在,引用Rhino书摘录的答案是正确的关于字符串不可变性,但错误的说“字符串是通过引用分配的,而不是通过值。”(可能他们最初的意思是反其道而行之)。
“引用/值”的误解在“专业JavaScript”的“原语和参考值”一章中得到了澄清:
五种基本类型…[是]:未定义,空,布尔,数字和字符串。这些变量被称为通过值访问,因为您正在操作存储在变量中的实际值。 - Web开发人员专业JavaScript,第3版,第85页
与对象相反:
当您操作一个对象时,实际上是在处理对该对象的引用,而不是实际的对象本身。因此,这样的值被称为通过reference.-面向Web开发者的专业JavaScript,第3版,第85页访问
只是为了澄清像我这样头脑简单的人(from 中数):
不可变对象是一旦对象被创建,其状态就不能改变的对象。 字符串和数字是不可变的。
不可变对象是一旦对象被创建,其状态就不能改变的对象。
字符串和数字是不可变的。
不可变意味着:
你可以让一个变量名指向一个新的值,但是之前的值仍然保存在内存中。因此需要垃圾收集。 var immutableString = "Hello"; //在上面的代码中,创建了一个string值的新对象。 immutableString = immutableString + "World"; //我们现在追加“;world &;到现有值。
你可以让一个变量名指向一个新的值,但是之前的值仍然保存在内存中。因此需要垃圾收集。
var immutableString = "Hello";
//在上面的代码中,创建了一个string值的新对象。
immutableString = immutableString + "World";
//我们现在追加“;world &;到现有值。
这看起来像是我们在改变字符串'immutableString',但我们没有。而不是:
关于添加“immutablestring”;使用字符串值,会发生以下事件: immutablestring的现有值;检索 “World"被追加到现有的值&;immutablestring &; 然后将结果值分配给一个新的内存块 “immutableString"对象现在指向新创建的内存空间 以前创建的内存空间现在可用于垃圾收集。
关于添加“immutablestring”;使用字符串值,会发生以下事件: