JavaScript 문자열은 변경할 수 없나요?JavaScript에 "문자열 작성기"가 필요합니까?

StackOverflow https://stackoverflow.com/questions/51185

  •  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는 내 테스트에 결함이 있다고 생각했기 때문에 동일한 문자열을 연결하여 큰 문자열을 생성하지 않고 각 반복마다 다른 문자를 사용하는 새 사례를 만들었습니다.문자열 연결은 여전히 ​​더 빠르거나 그만큼 빠른 것처럼 보였습니다.해당 테스트를 실행해 보겠습니다.

나는 모든 사람들이 이것을 테스트하는 다른 방법을 계속 생각하고 아래의 다양한 테스트 사례에 대한 새로운 링크를 자유롭게 추가해야 한다고 제안합니다.

http://jsperf.com/string-concat-without-sringbuilder/7

다른 팁

~로부터 코뿔소 책:

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

한편, 새 속성을 추가할 수는 있지만 기존 속성을 변경할 수는 없습니다.

Chrome 콘솔 테스트 스크린샷

결론적으로, 1.모든 문자열 유형 값(기본 유형)은 변경할 수 없습니다.2.String 객체는 변경 가능하지만 포함된 문자열 유형 값(기본 유형)은 변경할 수 없습니다.

나와 같은 단순한 사람들을 위해 명확히 하기 위해(from MDN):

불변 객체는 객체가 생성되면 상태를 변경할 수 없는 객체입니다.

문자열과 숫자는 변경할 수 없습니다.

불변이란 다음을 의미합니다.

변수 이름이 새 값을 가리키도록 만들 수 있지만 이전 값은 여전히 ​​메모리에 유지됩니다.따라서 가비지 수집이 필요합니다.

var immutableString = "Hello";

// 위 코드에서는 문자열 값을 가진 새로운 객체가 생성됩니다.

immutableString = immutableString + "World";

// 이제 기존 값에 "World"를 추가합니다.

이는 'immutableString' 문자열을 변경하는 것처럼 보이지만 그렇지 않습니다.대신에:

"immutableString"에 문자열 값을 추가하면 다음 이벤트가 발생합니다.

  1. "immutableString"의 기존 값이 검색됩니다.
  2. "immutableString"의 기존 값에 "World"가 추가됩니다.
  3. 그런 다음 결과 값이 새 메모리 블록에 할당됩니다.
  4. "immutableString" 객체는 이제 새로 생성된 메모리 공간을 가리킵니다.
  5. 이전에 생성된 메모리 공간을 이제 가비지 수집에 사용할 수 있습니다.

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의 문자열은 변경할 수 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top