답변:
개체를 인스턴스화하면 속성을 변경할 수 없음을 의미합니다. 첫 번째 경고에서 foo를 변경하지 않습니다. 새 문자열을 만들고 있습니다. 이것이 두 번째 경고에서 oo 대신 "foo"를 표시하는 이유입니다.
문자열에 대해 메서드를 호출 할 때 수정 된 문자열을 반환하지만 초기 문자열은 변경하지 않는다는 의미입니까?
예. 문자열이 생성되면 아무것도 변경할 수 없습니다. 이제 이것이 str
변수에 새 문자열 객체를 할당 할 수 없다는 의미는 아닙니다 . str이 참조하는 현재 객체를 변경할 수 없습니다.
문자열이 변경 가능하다면 두 번째 alert ()도 oo를 반환한다는 의미입니까?
기술적으로는 아니요, 하위 문자열 메서드가 새 문자열을 반환하기 때문입니다. 객체를 변경 가능하게 만들어도 메서드가 변경되지 않습니다. 변경 가능하게 만드는 것은 기술적으로 하위 문자열이 새 문자열을 만드는 대신 원래 문자열을 변경하도록 만들 수 있음을 의미합니다.
낮은 수준에서 불변성은 문자열이 저장된 메모리가 수정되지 않음을 의미합니다. 문자열을 생성 "foo"
하면 값을 저장하기 위해 일부 메모리가 할당됩니다 "foo"
. 이 메모리는 변경되지 않습니다. 예를 들어를 사용하여 문자열을 수정하면 substr(1)
새 문자열이 생성되고을 저장할 메모리의 다른 부분이 할당됩니다 "oo"
. 이제 메모리에 두 개의 문자열이 "foo"
있고 "oo"
. "foo"
더 이상 사용하지 않더라도 쓰레기가 수거 될 때까지 계속 붙어 있습니다.
문자열 연산이 상대적으로 비용이 많이 드는 이유 중 하나입니다.
불변이란 변경하거나 수정할 수 없음을 의미합니다.
따라서 문자열에 값을 할당 할 때이 값은 대체되는 것이 아니라 처음부터 만들어집니다. 따라서 동일한 문자열에 새 값이 할당 될 때마다 복사본이 생성됩니다. 따라서 실제로는 원래 값을 변경하지 않습니다.
JavaScript에 대해 확신 할 수는 없지만 Java에서 문자열은 "문자열 상수 풀"을 사용하여 불변성에 대한 추가 단계를 수행합니다. 문자열은 문자열 리터럴 ( "foo"
) 또는 String
클래스 생성자를 사용하여 생성 할 수 있습니다 . 문자열 리터럴로 구성된 문자열은 문자열 상수 풀의 일부이며 동일한 문자열 리터럴은 항상 풀의 동일한 메모리 주소가됩니다.
예:
String lit1 = "foo";
String lit2 = "foo";
String cons = new String("foo");
System.out.println(lit1 == lit2); // true
System.out.println(lit1 == cons); // false
System.out.println(lit1.equals(cons)); // true
위의 경우 lit1
및 둘 다 lit2
동일한 문자열 리터럴을 사용하여 구성되므로 동일한 메모리 주소를 가리키고 있습니다. lit1 == lit2
결과 true
는 정확히 동일한 객체이기 때문입니다.
그러나 cons
클래스 생성자를 사용하여 생성됩니다. 파라미터가 동일한 문자열 상수이지만, 새로운 메모리의 생성자 할당은 cons
의미가 cons
같은 오브젝트가 아닌 lit1
와 lit2
동일한 데이터를 포함 불구.
물론 세 문자열은 모두 동일한 문자 데이터를 포함하므로 equals
메서드를 사용하면 true가 반환됩니다.
(물론 두 가지 유형의 문자열 구성은 변경할 수 없습니다.)
변경 가능성의 교과서 정의는 책임이 있거나 변경 또는 변경 될 수 있습니다. 프로그래밍에서 우리는 시간이 지남에 따라 상태가 변경 될 수있는 객체를 의미하는 단어를 사용합니다. 변경 불가능한 값은 정반대입니다. 생성 된 후에는 변경할 수 없습니다.
이것이 이상하게 느껴진다면, 우리가 항상 사용하는 많은 값들은 사실상 불변이라는 것을 상기시켜 드리겠습니다.
var statement = "I am an immutable value";
var otherStr = statement.slice(8, 17);
두 번째 줄이 문장의 문자열을 변경하지 않는다는 사실에 아무도 놀라지 않을 것이라고 생각합니다. 사실, 문자열 메서드는 작동하는 문자열을 변경하지 않으며 모두 새 문자열을 반환합니다. 그 이유는 문자열은 불변이기 때문입니다. 문자열은 변경할 수 없으며 새로운 문자열 만 만들 수 있습니다.
문자열은 JavaScript에 내장 된 유일한 불변 값이 아닙니다. 숫자도 변경할 수 없습니다. 표현 2 + 3을 평가하면 숫자 2의 의미가 바뀌는 환경을 상상할 수 있습니까? 어리석게 들리지만 우리는 항상 객체와 배열로 이것을합니다.
문자열에서 스택까지 ... Eric Lippert의 블로그 에서 가져온 이해하기 쉬운 예제 :
C # 3.0에서 A *를 사용한 경로 찾기, 2 부 ...
System.Collections.Generic.Stack과 같은 변경 가능한 스택은 분명히 적합하지 않습니다. 우리는 기존 경로를 가져 와서 마지막 요소의 모든 이웃에 대해 새 경로를 만들 수 있기를 원하지만 새 노드를 표준 스택에 푸시하면 스택이 수정됩니다. 스택을 푸시하기 전에 복사본을 만들어야하는데, 이는 모든 내용을 불필요하게 복제 할 것이기 때문입니다.
불변 스택에는이 문제가 없습니다. 변경 불가능한 스택에 밀어 넣으면 기존 스택을 꼬리로 연결하는 새로운 스택이 생성됩니다. 스택은 불변이기 때문에 다른 코드가 따라 와서 꼬리 내용을 엉망으로 만들 위험이 없습니다. 이전 스택을 마음껏 사용할 수 있습니다.
불변성을 이해하려면 다음으로 시작하는 Eric의 게시물을 읽어보십시오.
이 개념을 이해하는 한 가지 방법은 자바 스크립트가 모든 객체를 처리하는 방법을 참조하는 것입니다. 즉, 모든 개체는 인스턴스화 후 변경 가능 합니다. 즉, 새 메서드와 속성을 사용하여 개체를 추가 할 수 있습니다. 개체를 변경 불가능하게하려면 인스턴스화 된 후에 개체를 변경할 수 없기 때문에 이는 중요합니다.