JavaScript 문자열은 변경할 수 없나요?JavaScript에 "문자열 작성기"가 필요합니까?
-
09-06-2019 - |
문제
자바스크립트는 불변 또는 가변 문자열을 사용합니까?"스트링 빌더"가 필요합니까?
해결책
그것들은 불변입니다.다음과 같은 문자열 내의 문자를 변경할 수 없습니다. var myString = "abbdef"; myString[2] = 'c'
.다음과 같은 문자열 조작 방법 trim
, slice
새로운 문자열을 반환합니다.
같은 방식으로 동일한 문자열에 대한 두 개의 참조가 있는 경우 하나를 수정해도 다른 참조에는 영향을 미치지 않습니다.
let a = b = "hello";
a = a + " world";
// b is not affected
그러나 나는 Ash가 그의 대답에서 Array.join을 사용하는 것이 연결에 더 빠르다는 것을 항상 들었기 때문에 문자열을 연결하고 가장 빠른 방법을 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"
빈 문자열로 십만 번.
세 가지 유형의 테스트를 만들었습니다.
- 사용
Array.push
그리고Array.join
- 피하기 위해 배열 인덱싱 사용
Array.push
, 다음을 사용하여Array.join
- 직선 문자열 연결
그런 다음 동일한 세 가지 테스트를 추상화하여 만들었습니다. StringBuilderConcat
, StringBuilderArrayPush
그리고 StringBuilderArrayIndex
http://jsperf.com/string-concat-without-sringbuilder/5 좋은 샘플을 얻을 수 있도록 그곳으로 가서 테스트를 실행해 보세요.작은 버그를 수정하여 테스트 데이터가 지워졌으므로 성능 데이터가 충분해지면 표를 업데이트하겠습니다.이동 http://jsperf.com/string-concat-without-sringbuilder/5 이전 데이터 테이블의 경우.
링크를 따라가고 싶지 않다면 여기에 몇 가지 숫자(Ma5rch 2018의 최신 업데이트)가 있습니다.각 테스트의 수는 1000 작업/초입니다(높을수록 좋다)
| Browser | Index | Push | Concat | SBIndex | SBPush | SBConcat |
---------------------------------------------------------------------------
| Chrome 71.0.3578 | 988 | 1006 | 2902 | 963 | 1008 | 2902 |
| Firefox 65 | 1979 | 1902 | 2197 | 1917 | 1873 | 1953 |
| Edge | 593 | 373 | 952 | 361 | 415 | 444 |
| Exploder 11 | 655 | 532 | 761 | 537 | 567 | 387 |
| Opera 58.0.3135 | 1135 | 1200 | 4357 | 1137 | 1188 | 4294 |
결과
요즘 모든 에버그린 브라우저는 문자열 연결을 잘 처리합니다.
Array.join
IE 11에만 도움이 됩니다.전반적으로 Opera는 가장 빠르며 Array.join보다 4배 빠릅니다.
Firefox는 두 번째이며
Array.join
FF에서는 약간 느리지만 Chrome에서는 상당히 느립니다(3배).Chrome은 세 번째이지만 문자열 연결은 Array.join보다 3배 빠릅니다.
StringBuilder를 생성하면 성능에 큰 영향을 미치지 않는 것 같습니다.
다른 사람이 이것이 유용하다고 생각하기를 바랍니다.
다른 테스트 케이스
@RoyTinker는 내 테스트에 결함이 있다고 생각했기 때문에 동일한 문자열을 연결하여 큰 문자열을 생성하지 않고 각 반복마다 다른 문자를 사용하는 새 사례를 만들었습니다.문자열 연결은 여전히 더 빠르거나 그만큼 빠른 것처럼 보였습니다.해당 테스트를 실행해 보겠습니다.
나는 모든 사람들이 이것을 테스트하는 다른 방법을 계속 생각하고 아래의 다양한 테스트 사례에 대한 새로운 링크를 자유롭게 추가해야 한다고 제안합니다.
다른 팁
~로부터 코뿔소 책:
JavaScript에서 문자열은 불변의 객체이므로 그 내의 문자가 변경되지 않을 수 있으며 문자열의 모든 작업이 실제로 새로운 문자열을 만듭니다.문자열은 값이 아닌 참조별로 할당됩니다.일반적으로 객체가 참조로 할당되면 한 참조를 통해 객체로의 변경이 객체에 대한 다른 모든 참조를 통해 볼 수 있습니다.그러나 문자열을 변경할 수 없으므로 문자열 객체에 대한 여러 참조를 가질 수 있으며 문자열 값이 당신이 알지 못하고 변경 될 것이라고 걱정하지 않습니다.
성능 팁:
큰 문자열을 연결해야 하는 경우 문자열 부분을 배열에 넣고 Array.Join()
전체 문자열을 얻는 방법.많은 수의 문자열을 연결하는 경우 이 방법이 몇 배 더 빠를 수 있습니다.
없다 StringBuilder
자바스크립트에서.
문자열은 불변이다 – 그것들은 바뀔 수 없으며, 우리는 단지 새로운 끈을 만들 수 있을 뿐입니다.
예:
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' }
한편, 새 속성을 추가할 수는 있지만 기존 속성을 변경할 수는 없습니다.
결론적으로, 1.모든 문자열 유형 값(기본 유형)은 변경할 수 없습니다.2.String 객체는 변경 가능하지만 포함된 문자열 유형 값(기본 유형)은 변경할 수 없습니다.
나와 같은 단순한 사람들을 위해 명확히 하기 위해(from MDN):
불변 객체는 객체가 생성되면 상태를 변경할 수 없는 객체입니다.
문자열과 숫자는 변경할 수 없습니다.
불변이란 다음을 의미합니다.
변수 이름이 새 값을 가리키도록 만들 수 있지만 이전 값은 여전히 메모리에 유지됩니다.따라서 가비지 수집이 필요합니다.
var immutableString = "Hello";
// 위 코드에서는 문자열 값을 가진 새로운 객체가 생성됩니다.
immutableString = immutableString + "World";
// 이제 기존 값에 "World"를 추가합니다.
이는 'immutableString' 문자열을 변경하는 것처럼 보이지만 그렇지 않습니다.대신에:
"immutableString"에 문자열 값을 추가하면 다음 이벤트가 발생합니다.
- "immutableString"의 기존 값이 검색됩니다.
- "immutableString"의 기존 값에 "World"가 추가됩니다.
- 그런 다음 결과 값이 새 메모리 블록에 할당됩니다.
- "immutableString" 객체는 이제 새로 생성된 메모리 공간을 가리킵니다.
- 이전에 생성된 메모리 공간을 이제 가비지 수집에 사용할 수 있습니다.
ASP.NET Ajax의 StringBuilder에 대한 귀하의 질문(Ash의 응답에 대한 귀하의 의견)과 관련하여 전문가들은 이에 동의하지 않는 것 같습니다.
크리스티안 웬츠(Christian Wenz)는 그의 책에서 이렇게 말합니다. ASP.NET AJAX 프로그래밍 (O'Reilly)는 "이 접근 방식은 메모리에 측정 가능한 영향을 미치지 않습니다(실제로 구현은 표준 접근 방식보다 한 눈금 느린 것 같습니다)."라고 말했습니다.
반면에 Gallo 등은 그들의 책에서 다음과 같이 말합니다. ASP.NET AJAX 실행 (Manning) "연결할 문자열 수가 많아지면 문자열 빌더는 엄청난 성능 저하를 방지하는 데 필수적인 개체가 됩니다."
벤치마킹을 직접 수행해야 하며 결과는 브라우저마다 다를 수도 있습니다.그러나 성능이 향상되지 않더라도 C# 또는 Java와 같은 언어로 StringBuilder를 사용하여 코딩하는 데 익숙한 프로그래머에게는 여전히 "유용한" 것으로 간주될 수 있습니다.
늦은 포스팅인데 답변중에 좋은 책 명언을 못찾았네요.
신뢰할 만한 책을 제외하고는 다음과 같은 확실한 사실이 있습니다.
문자열은 ECMAScript에서 불변입니다. 즉, 일단 생성되면 값이 변경될 수 없습니다.변수가 보유한 문자열을 변경하려면 원래 문자열을 삭제하고 변수를 새 값을 포함하는 다른 문자열로 채워야 합니다. —웹 개발자를 위한 전문 JavaScript, 3판, p.43
이제 Rhino Book의 발췌를 인용하는 대답은 문자열 불변성에 대해 옳지 만 "문자열은 가치가 아닌 참조로 할당됩니다." (아마도 그들은 원래 그 단어를 반대 방향으로 두려고했을 것입니다).
"참조/값"에 대한 오해는 "전문 JavaScript"의 "기본 및 참조 값" 장에서 명확하게 설명됩니다.
다섯 가지 기본 유형은...[다음과 같습니다]:정의되지 않음, Null, 부울, 숫자 및 문자열.변수에 저장된 실제 값을 조작하기 때문에 이러한 변수를 값으로 액세스한다고 합니다. —웹 개발자를 위한 전문 JavaScript, 3판, p.85
그건 반대야 사물:
객체를 조작할 때 실제로는 실제 객체 자체가 아닌 해당 객체에 대한 참조를 작업하는 것입니다.이러한 이유로 이러한 값은 참조로 액세스된다고 합니다.—웹 개발자를 위한 전문 JavaScript, 3판, p.85
JavaScript 문자열은 실제로 변경할 수 없습니다.
Javascript의 문자열은 변경할 수 없습니다.