>  기사  >  웹 프론트엔드  >  javascript_javascript 스킬의 삭제 사용법에 대한 자세한 설명

javascript_javascript 스킬의 삭제 사용법에 대한 자세한 설명

WBOY
WBOY원래의
2016-05-16 17:37:341327검색

이 글에서 저자는 책 "JavaScript Object-Oriented 프로그래밍 가이드"에 나오는 삭제에 대한 오류부터 시작하여 다양한 브라우저와 플러그인에서의 삭제 작업의 구현, 제한 사항 및 문제점을 자세히 설명합니다(여기서는 방화범을 가리킴). 성능.

아래 주요 부분을 번역했습니다.

...책 속 주장

“함수는 일반 변수와 같습니다. 다른 변수에 복사하거나 삭제할 수도 있습니다.”

그리고 설명으로 다음 코드 조각을 첨부했습니다.

코드 복사 코드는 다음과 같습니다.

>>> var sum = function(a, b) {return a b;};
>>> var add = sum;
>>> sum;
true
>>> sum;
"정의되지 않음"

클립에서 문제를 발견할 수 있나요? 문제는 sum 변수를 삭제하면 성공하지 못한다는 것입니다. 삭제 선언은 true를 반환해서는 안 되며 typeof sum은 정의되지 않은 값을 반환해서는 안 됩니다. JavaScript에서는 변수를 삭제할 수 없기 때문에 적어도 이런 방식으로는 삭제할 수 없습니다.

이 예에서는 무슨 일이 일어나고 있나요? 오타인가요 아니면 농담인가요? 아마도 그렇지 않을 것입니다. 이 조각은 Stoyan(위에서 언급한 책의 저자)이 빠른 테스트를 위해 사용한 것으로 추정되는 Firebug 콘솔의 실제 출력입니다. 이는 Firebug에 다른 삭제 규칙이 있음을 나타내는 것 같습니다. 스토얀을 속인 것은 방화범이었습니다! 그럼 여기서 무슨 일이 일어나고 있는 걸까요?

이 질문에 답하려면 Javascript에서 삭제 연산자가 어떻게 작동하는지, 즉 삭제할 수 있는 항목과 삭제할 수 없는 항목 및 그 이유를 이해해야 합니다. 아래에서는 이에 대한 세부 사항을 설명하려고 합니다. 우리는 Firebug의 "이상한" 동작을 살펴보고 실제로는 전혀 "이상한" 것이 아니라는 사실을 깨닫게 될 것입니다. 변수, 함수를 선언하고 속성을 할당하고 삭제할 때 그 이면의 세부 사항을 살펴보겠습니다. 브라우저 구현과 몇몇 유명한 버그에 대해서도 ECMAScript 버전 5의 엄격 모드와 이것이 삭제 연산자의 동작을 변경하는 방법에 대해 논의할 것입니다.

저는 일반적으로 ECMAScript를 지칭하기 위해 아래에서 Javascript와 ECMPScript를 같은 의미로 사용합니다(Mozilla의 JavaScript™ 구현을 명시적으로 언급하는 경우는 제외).

역시 현재 인터넷에는 삭제에 대한 설명이 거의 없습니다(작성자 주: 이 글은 2010년 1월에 작성되었습니다). MDC(MDN]) 리소스는 아마도 가장 자세하게 설명되어 있지만 불행히도 위에서 언급한 방화범의 이상한 동작을 포함하여 몇 가지 흥미로운 세부 정보가 빠져 있습니다. MSDN 문서는 거의 쓸모가 없습니다.

1. 이론 | 이론
그러면 왜 객체의 속성을 삭제할 수 있나요?

코드 복사 코드는 다음과 같습니다.

var x = { a: 1 }
delete x.a; // true
x.a; / 정의되지 않음


하지만 변수를 삭제할 수는 없습니다.
코드 복사 코드는 다음과 같습니다. 다음과 같습니다:

var x = 1;
delete x; // false
x; // 1

함수도 삭제할 수 없습니다. :
코드 복사 코드는 다음과 같습니다.

function x() {}; 🎜>delete x; // false
typeof x; // "함수"


참고: 삭제는 속성을 삭제할 수 없는 경우에만 false를 반환합니다.

이를 이해하려면 먼저 변수 인스턴스화 및 속성 속성이라는 몇 가지 개념을 파악해야 합니다. (역자 주: 속성과 속성의 차이점에 대해서는 참조 기사를 참조하세요. 아래에 관련된 내용은 내부 속성으로 변환됨) - JavaScript 책에서는 거의 언급되지 않습니다. 다음 단락에서 나는 이것들을 간략하게 검토하려고 노력할 것입니다. 그것들을 이해하는 것은 어렵지 않습니다. 성능 이면의 이유에 관심이 없다면 이 장을 건너뛰어도 됩니다.

1.1 코드 종류 | 코드 종류

ECMAScript에는 세 가지 유형의 실행 코드가 있습니다.

1.글로벌 코드 글로벌 코드
2. 함수 코드 함수 코드
3.평가 코드

카테고리는 이름과 거의 비슷하지만 간단히 요약하면 다음과 같습니다.

1. 소스 파일을 프로그램으로 간주하면 전역 범위(scope) 내에서 실행되며, 이는 전역 코드의 일부로 간주됩니다. 브라우저 환경에서 SCRIPT 요소의 내용은 일반적으로 프로그램으로 구문 분석되므로 전역 코드로 실행됩니다.

2. 물론 함수에서 직접 실행되는 코드는 모두 함수 코드로 간주됩니다. 브라우저 환경에서는 이벤트 속성(예:

3. 마지막으로 내장 함수 eval에 배치된 코드를 Eval 코드로 파싱합니다. 우리는 이 유형이 왜 특별한지 곧 알게 될 것입니다.

1.2.코드 실행 컨텍스트 | 실행 컨텍스트
ECMAScript 코드가 실행되면 항상 특정 실행 컨텍스트(context)에서 발생합니다. 실행 범위는 범위 및 변수 인스턴스화가 작동하는 방식을 이해하는 데 도움이 되는 추상 엔터티입니다. 위의 세 가지 유형의 실행 코드에는 고유한 실행 컨텍스트가 있습니다. 함수 코드가 실행되면 제어 쪽이 함수 코드의 실행 컨텍스트에 들어간다고 말하고, 글로벌 코드가 실행되면 컨트롤 쪽이 글로벌 코드의 실행 컨텍스트에 들어간다고 말합니다.

보시다시피 실행 컨텍스트는 논리적으로 스택입니다. 첫째, 자체 실행 컨텍스트가 있는 전역 코드가 있을 수 있습니다. 이 코드에서 함수가 호출될 수 있으며 이 함수도 자체 실행 컨텍스트를 가질 수 있습니다. 함수가 자신을 재귀적으로 호출하는 경우에도 호출할 때마다 다른 실행 컨텍스트가 입력됩니다.

1.3.활성화 객체와 변수 객체 | 활성화 객체/변수 객체
각 실행 컨텍스트에는 그에 연결된 변수 객체(변수 객체)가 있습니다. 마찬가지로, 변수 개체는 변수 인스턴스화를 설명하는 데 사용되는 메커니즘인 추상 엔터티입니다. 흥미로운 점은 소스 코드에서 선언된 변수와 함수가 실제로 변수 개체의 속성으로 변수 개체에 추가된다는 것입니다.

제어가 전역 코드의 실행 컨텍스트에 들어갈 때 전역 개체가 변수 개체로 사용됩니다. 이것이 바로 전역적으로 선언된 변수와 함수가 전역 개체의 속성이 되는 이유입니다.

코드 복사 코드는 다음과 같습니다.

var GLOBAL_OBJECT = this;
var foo = 1;
GLOBAL_OBJECT.foo; // 1
function bar() {};
GLOBAL_OBJECT.bar 유형; "함수"
GLOBAL_OBJECT.bar === bar // true

그래, 전역 변수는 전역 함수의 속성이 되지만 지역 변수(함수 코드에 선언된 변수)는 어떻습니까? 실제로는 매우 간단합니다. 변수 객체의 속성이기도 합니다. 유일한 차이점은 함수 코드에서 변수 개체가 전역 개체가 아니라 활성화 개체라고 부르는 것입니다. 함수 코드의 실행 컨텍스트가 입력될 때마다 활성화 개체가 생성됩니다.

함수 코드에 선언된 변수와 함수는 활성화 객체의 속성이 될 뿐만 아니라, 함수의 각 실제 매개변수(인수, 해당 형식 매개변수의 이름을 속성 이름으로 사용), 특수 Arguments 객체( 인수를 속성 이름으로 사용)도 활성화된 개체의 속성이 됩니다. 활성화 개체는 실제로 프로그램 코드에서 액세스할 수 없는 내부 메커니즘이라는 점에 유의해야 합니다.

코드 복사 코드는 다음과 같습니다.

(function(foo) {
var bar = 2;
function baz() {};
/*
추상화 과정에서
특수' 인수의 개체는 함수의 활성화 개체의 속성이 됩니다.
ACTIVATION_OBJECT.arguments = 인수;
...'foo' 매개변수에도 동일하게 적용됩니다.
ACTIVATION_OBJECT.foo; 🎜> ..'bar' 변수는 동일합니다:
ACTIVATION_OBJECT.bar; // 2
  ...'baz' 함수는 동일합니다:
typeof ACTIVATION_OBJECT.baz; function"
*/
}) (1);

마지막으로 Eval 코드에서 선언된 변수는 컨텍스트의 Variable 개체의 특성이 됩니다. 평가 코드는 호출 시 실행 컨텍스트의 변수 개체를 사용합니다.

코드 복사 코드는 다음과 같습니다.
var GLOBAL_OBJECT = this;
eval ('var foo = 1');
GLOBAL_OBJECT.foo // 1;
(function() {

eval('var bar = 2');

/*

추상화 프로세스 중
ACTIVATION_OBJECT.bar; // 2
*/
}) ();

1.4. 속성의 내부 속성

이 주제에 가깝습니다. 이제 우리는 변수에 어떤 일이 일어나는지(속성이 됨) 알았으므로 이해해야 할 남은 개념은 속성의 내부 속성(속성 속성)입니다. 각 속성에는 0개 이상의 내부 속성(*ReadOnly, DontEnum, DontDelete 및 Internal**)이 있습니다. 태그로 생각할 수 있습니다. 속성에는 특별한 내부 속성이 있을 수도 있고 없을 수도 있습니다. 오늘 토론에서는 DontDelete에 관심이 있습니다.

변수와 함수가 선언되면 변수 객체(함수 코드의 경우) 또는 전역 객체(전역 코드의 경우)의 속성이 됩니다. 이러한 속성은 내부 속성인 DontDelete가 생성됩니다. 그러나 명시적/암시적으로 할당된 속성은 DontDelete를 생성하지 않습니다. 이것이 본질적으로 일부 속성은 삭제할 수 있지만 다른 속성은 삭제할 수 없는 이유입니다.

코드 복사 코드는 다음과 같습니다.
var GLOBAL_OBJECT = this;
/* 'foo'는 전역 객체의 속성입니다.

변수 선언을 통해 생성되므로 DontDelete 내부 속성을 갖습니다.
삭제할 수 없는 이유입니다.*/
var foo = 1;
foo 삭제; // false
foo 유형 // "숫자"

/* 'bar'는 전역 개체의 속성입니다.

변수 선언을 통해 생성되므로 DontDelete 하위 항목이 있습니다.
따라서 삭제할 수도 없습니다.*/
function bar () { };
delete bar; // false
typeof bar; // "함수"

/* 'baz'도 전역 개체의 속성입니다.

단, 속성 할당을 통해 생성되므로 DontDelete가 없습니다.
그렇기 때문에 삭제할 수 있습니다*/
GLOBAL_OBJECT. baz = " baz";
delete GLOBAL_OBJECT.baz; // true
GLOBAL_OBJECT.baz 유형; // "정의되지 않음"

1.5, 내장 및 DontDelete | 내장 및 DontDelete

이것이 바로 이 모든 일이 일어나는 이유입니다. 속성의 특별한 내부 속성이 속성 삭제 가능 여부를 제어합니다. 참고: 내장 개체의 일부 속성에는 내부 속성 DontDelete가 있으므로 삭제할 수 없습니다. 특수 인수 변수(우리가 알고 있듯이 활성화된 개체의 속성)에는 모든 함수 인스턴스의 길이(반환 매개 변수 길이) 속성도 있습니다. 삭제하지 마세요:

코드 복사 코드는 다음과 같습니다.
(function() {
/ /'인수'는 삭제할 수 없습니다. DontDelete
인수 삭제; // false;
인수 유형; // "object"
//함수 길이는 DontDelete

function f() {};
delete f.length; // false;
typeof f.length; 번호"
}) ();

함수 인수와 관련된 속성에도 DontDelete가 있으므로 삭제할 수 없습니다.

코드 복사 코드는 다음과 같습니다.

(function(foo,bar) {
foo 삭제 // false
foo // 1

삭제 막대; // false
bar; // "바"
}) (1,"바");

1.6.선언되지 않은 변수 할당 | 선언되지 않은 할당
선언되지 않은 변수 할당은 이 속성이 범위 체인의 다른 곳에서 발견되지 않는 한 전역 개체의 속성이 된다는 것을 기억할 수 있습니다. 이제 우리는 속성 할당과 변수 선언의 차이점을 이해합니다. 후자는 DontDelete를 생성하고 전자는 생성하지 않습니다. 이것이 바로 선언되지 않은 변수 할당을 삭제할 수 있는 이유입니다.

코드 복사 코드는 다음과 같습니다.

var GLOBAL_OBJECT = this;

/* DontDelete를 사용하여 변수 선언을 통해 전역 객체 속성 생성 */
var foo = 1;

/* 선언되지 않은 변수 할당을 통해 전역 개체 속성을 생성합니다. DontDelete는 사용하지 않습니다. */
bar = 2;

delete foo; // false
delete bar; // true
참고: 내부 속성은 속성이 생성될 때 결정되며 후속 할당 프로세스는 기존 속성의 내부 속성을 변경하지 않습니다. 이 차이점을 이해하는 것이 중요합니다.

/* DontDelete는 'foo'가 생성될 때 생성됩니다. */
function foo() {};

/* 후속 할당 프로세스는 기존 속성의 내부 속성을 변경하지 않습니다. DontDelete는 여전히 존재합니다*/
foo = 1;
delete foo; // false;
typeof foo; "번호"

/* 하지만 존재하지 않는 속성을 할당하면 내부 속성이 없는 속성이 생성되므로 DontDelete가 없습니다. */
this.bar = 1;
delete bar;
bar 유형; // "정의되지 않음"

2. 파이어버그 혼란 | 파이어버그 혼란

그럼 방화범에서는 무슨 일이 벌어지고 있는 걸까요? 이전에 설명한 것과 달리 콘솔에 선언된 변수를 삭제할 수 있는 이유는 무엇입니까? 앞에서 Eval 코드는 변수 선언을 처리할 때 특별한 동작을 한다고 말했습니다. Eval 코드에서 선언된 변수는 실제로 DontDelete 없이 속성을 생성합니다.

코드 복사 코드는 다음과 같습니다.

eval('var foo = 1;' );
foo; // 1
delete foo; // true
foo 유형; // "정의되지 않음"

함수 코드에서도 마찬가지입니다.

코드 복사 코드는 다음과 같습니다.

(function () {
eval('var foo = 1;');
foo; // 1
delete foo; // true
typeof foo; // "정의되지 않음 "
}) ();

그리고 이것이 Firebug에서 예상치 못한 동작이 발생하는 이유입니다. 콘솔의 모든 디버깅 텍스트는 전역 코드나 함수 코드가 아닌 Eval 코드에서 컴파일되고 실행되는 것으로 나타납니다. 분명히 변수 선언은 결국 DontDelete 없이 속성을 생성하므로 삭제할 수 있습니다. 따라서 일반 전역 코드와 Firebug 콘솔 코드의 차이점에 주의하세요.

2.1. eval을 통해 변수 삭제
ECMAScript의 또 다른 측면과 결합된 이 흥미로운 평가 동작을 사용하면 원래 삭제할 수 없는 속성을 기술적으로 삭제할 수 있습니다. 이 측면은 함수 선언에 관한 것입니다. 동일한 실행 컨텍스트에서 동일한 이름의 변수를 재정의할 수 있습니다.

코드 복사 코드는 다음과 같습니다.

function x() { };
var x ;
typeof x; // "function"

그렇다면 함수 선언이 우선순위를 갖고 동일한 이름(즉, 동일한 속성)을 가진 변수를 재정의할 수 있는 이유는 무엇입니까? 변수 개체의)? 이는 함수 선언이 변수 선언 다음에 인스턴스화되므로 재정의될 수 있기 때문입니다.

(역자 주: 함수 선언은 선언되었지만 할당되지 않은 동일한 이름의 변수만 덮어쓸 수 있습니다. 선언 시 값이 할당된 경우(예: var x = 1), 값을 할당하는 과정은 다음과 같습니다. 는 함수가 초기화된 후이고 함수 선언은 다음과 같이 할당으로 대체됩니다. :)

코드 복사 코드는 다음과 같습니다.

var x = 1
function x() { };
typeof x; >

함수 선언은 속성 값뿐만 아니라 내부 속성도 대체합니다. eval을 통해 함수를 선언하면 이 함수는 이전 함수를 자체 내부 속성으로 대체합니다. eval에서 선언된 변수에 의해 생성된 속성에는 DontDelete가 없으므로 이 함수를 인스턴스화하면 "이론적으로" 원래 속성의 기존 DontDelete 내부 속성이 제거되어 이 속성이 삭제될 수 있습니다. 새로 생성된 함수).

코드 복사 코드는 다음과 같습니다.

var x = 1;
/ *삭제할 수 없습니다. 'x'에는 DontDelete*/
delete x; // false
typeof x; eval('function x() { }');

/* 이제 속성 'x'가 함수를 가리키며 DontDelete가 없어야 합니다. */
typeof x; >delete x ; // 'true'여야 합니다;
typeof x; // "정의되지 않음"이어야 합니다


안타깝게도 이 스푸핑 기술은 제가 시도한 모든 브라우저에서 성공하지 못했습니다. 여기에 뭔가 빠졌을 수도 있고 동작이 너무 미묘해서 개별 브라우저가 이를 알아차리지 못할 수도 있습니다.

(역자 주: 여기서 문제는 함수 선언과 변수 선언 사이의 재정의가 가리키는 값만 변경되는 반면 내부 속성 DontDelete는 초기 선언에서 결정되어 더 이상 변경되지 않는다는 점일 수 있습니다. eval과 함수에 선언된 경우, 외부 컨텍스트에서 선언되지 않은 부분만 삭제할 수 있습니다. 실행 순서와 관련하여 eval은 함수이므로 호출은 항상 외부 컨텍스트에서 다른 변수와 함수가 선언된 이후에 이루어집니다. 관련 내부 속성 값에 대한 포인터만 포함되는 것으로 확인되었습니다 :)


코드 복사 코드는
/* 할당 프로세스가 선언 프로세스 및 평가 실행 프로세스 이후이기 때문에 첫 번째 경고는 "정의되지 않음"을 반환합니다.
두 번째 경고는 "false"를 반환합니다. x 선언이 eval 뒤에 있습니다.
단, eval은 변수 선언 이후에 실행되므로 삭제할 수 없습니다*/
eval(' ​​​​alert( x ); Alert(delete x) ');
var x = 1;


3. 브라우저 규정 준수


작동 방식을 이해하는 것도 중요하지만 실제 구현이 더욱 중요합니다. 변수/속성을 생성하고 삭제할 때 브라우저는 이러한 표준을 준수합니까? 대부분 그렇습니다.
글로벌 코드, 함수 코드, Eval 코드의 준수 여부를 확인하기 위해

간단한 테스트 유닛

을 작성했습니다. 테스트 유닛은 삭제 작업의 반환 값과 속성이 예상대로 삭제되었는지 여부도 확인합니다. 삭제의 반환 값은 실제 결과만큼 중요하지 않습니다. 삭제 작업이 true 또는 false를 반환하는지 여부는 중요하지 않습니다. DontDelete가 포함된 속성이 삭제되었는지 여부는 중요하지 않습니다. 최신 브라우저는 일반적으로 삭제 규칙을 준수합니다. 다음 브라우저는 모두 테스트를 통과했습니다: Opera 7.54, Firefox 1.0, Safari 3.1.2, Chrome 4.

Safari 2.x 및 3.0.4에서는 함수 인수 삭제에 문제가 있는데, 이러한 속성은 DontDelete 없이 생성되므로 삭제할 수 있는 것 같습니다. Safari 2.x에는 다른 문제가 있습니다. 참조 없이 삭제할 때 오류가 발생합니다(예: delete 1). (번역자 참고: IE에도 이 기능이 있습니다. 이상하게도 변수 선언은 잘 작동합니다.) eval은 삭제할 수 없게 됩니다(그러나 eval의 함수 선언은 정상입니다).

Safari와 마찬가지로 Konqueror(4.3이 아닌 3.5)도 참조 없이 삭제하고 인수를 삭제하는 것과 동일한 문제가 있습니다.

3.1, Gecko 버그 삭제하지 마세요

Gecko 1.8.x 브라우저(Firefox 2.x, Camino 1.x, Seamonkey 1.x 등)에는 흥미로운 버그가 있습니다. A 속성에 값을 명시적으로 할당할 수 있습니다. 속성이 변수나 함수를 통해 선언된 경우에도 DontDelete가 제거됩니다.



function foo() { };
foo 삭제 ; // false;
foo 유형; // "함수"

this.foo = 1;delete foo; // true

typeof foo; // "정의되지 않음"

놀랍게도 IE5.5-8은 비참조를 삭제하면 오류가 발생하는 것을 제외하고 대부분의 테스트도 통과합니다(예: 기존 Safari와 마찬가지로 1 삭제). 그러나 즉시 명백하지는 않지만 IE에는 실제로 더 심각한 버그가 있으며 이러한 버그는 전역 개체와 관련이 있습니다.

4. IE 버그

IE(적어도 IE6-8)에서 다음 표현식은 예외를 발생시킵니다(전역 코드에서):

코드 복사 코드는 다음과 같습니다.

this.x = 1;
delete x; // TypeError: 개체가 이 작업을 지원하지 않습니다

여기 또 하나가 있습니다.

코드 복사 코드는 다음과 같습니다.

var x =1;
delete this.x ; // 유형 오류: 'this.x'를 삭제할 수 없습니다
// 번역자 참고 사항: 이 예외는 IE8에서 발생하며 위와 동일한 예외는 IE6 및 7에서도 발생합니다

이는 IE의 전역 코드에 있는 변수 선언이 전역 개체의 동일한 이름 속성을 생성하지 않음을 나타내는 것으로 보입니다. 할당으로 생성된 속성(this.x = 1)과 delete x로 삭제된 속성은 예외를 발생시킵니다. 변수 선언으로 생성된 후(var x = 1) 삭제된 this.x로 삭제된 속성은 또 다른 예외를 발생시킵니다. 오류 메시지는 IE6 및 7에서 위와 동일합니다.

그러나 그뿐만 아니라 실제로 명시적 할당을 통해 생성된 속성은 삭제 시 항상 예외를 발생시킵니다. 이것은 단순한 버그가 아니지만 생성된 속성에 DontDelete 내부 속성이 있는 것으로 보입니다. 규칙에 따르면 다음과 같은 속성이 있어서는 안 됩니다.

코드 복사 코드는 다음과 같습니다.

this.x = 1;
delete this. x; // TypeError: 개체가 이 작업을 지원하지 않습니다
delete x; // TypeError: 개체가 이 작업을 지원하지 않습니다

반면에 선언되지 않은 변수 할당(전역 개체를 생성하는 속성)은 실제로 IE에서 정상적으로 삭제될 수 있습니다.

코드 복사 코드는 다음과 같습니다.

x = 1;
delete x ; // 참

그런데 이 키워드를 통해 삭제하려고 하면(delete this.

요약해보면 'this.x 삭제'는 전역 코드에서 절대 성공하지 못한다는 것을 알 수 있습니다. 속성이 명시적 할당에 의해 생성되면(this.x = 1) 예외가 발생하고, 변수를 선언/선언 취소하여 속성이 생성되면(var x = 1 또는 x = 1) 또 다른 예외가 발생합니다. 반면에 x 삭제는 명시적 할당이 속성을 생성하는 경우에만 예외를 발생시킵니다(this.x = 1).


9월에 저는 이 문제에 대해 논의했습니다. 여기서

Garrett Smith
는 IE에서 전역 변수 개체(전역 변수 개체)가 JScript 개체로 구현되고 전역 개체는 다음과 같다고 믿었습니다. Host 객체 구현으로 표현됩니다.

이 이론을 어느 정도 확인하기 위해 여러 가지 테스트를 실행할 수 있습니다. this 와 window 는 동일한 객체를 참조하는 것으로 보이지만('===' 연산자를 신뢰할 수 있는 경우), Variable 객체(함수 선언의 기초)는 this 에서 참조하는 객체와 다릅니다.

코드 복사

코드는 다음과 같습니다.function getBase() { return this } ; getBase() === this.getBase(); // falsethis.getBase() === this.getBase(); // true
window.getBase() === this .getBase(); // 참
window.getBase() === getBase() // 거짓

5. 오해

사물이 어떻게 작동하는지 이해하는 것의 중요성을 과소평가할 수 없습니다. 인터넷에서 삭제 작업에 대한 몇 가지 오해를 본 적이 있습니다. 예를 들어 Stackoverflow에 대한 답변(및 매우 높은 순위의 답변)에서는 "대상이 객체 속성이 아닌 경우 삭제가 작동하지 않는 것으로 가정됩니다"라고 설명합니다. 이제 삭제 작업의 핵심을 이해했으므로 이 대답이 틀렸다는 것이 분명해졌습니다. delete는 변수와 속성(사실 삭제 작업의 참조)을 구별하지 않고 DontDelete(및 속성이 이미 존재하는지 여부)에만 관심을 갖습니다.

6. '삭제' 및 호스트 개체 | '삭제' 및 호스트 개체

삭제 알고리즘은 대략 다음과 같습니다.

1. 피연산자가 참조가 아니면 true를 반환합니다.
2. 객체에 동일한 이름의 **직접 속성**이 없으면 true를 반환합니다(아시다시피 객체는 전역 객체 또는 활성화 객체)
3. 속성이 이미 존재하지만 DontDelete가 있는 경우 false
를 반환합니다. 그렇지 않으면 속성을 삭제하고 true
를 반환합니다. 호스트 개체는 예측할 수 없습니다. 실제로 여기에는 아무런 문제가 없습니다. 호스트 객체는 (특정 규칙을 통해) 읽기(내부 [[Get]] 메서드), 쓰기(내부 [[Write]] 메서드), 삭제(내부 [ [삭제]] ] 방법) 등 사용자 정의 [[삭제]] 동작을 허용하면 호스트 개체에 혼란이 발생합니다.

특정 개체(호스트 개체로 구현된 개체)의 속성을 삭제할 때 예외가 발생하는 몇 가지 문제가 IE에서 확인되었습니다. 일부 Firefox 버전에서는 window.location을 삭제하려고 할 때 예외가 발생합니다(번역자 참고 사항: IE에서도 예외가 발생합니다). 마찬가지로 Firefox에서 발생한 것과 같은 일부 호스트 개체의 삭제 반환 값을 신뢰할 수 없습니다(번역자 참고: Chrome에서도 동일한 결과, IE에서는 예외가 발생함, Opera 및 Safari에서는 삭제를 허용하고 삭제 후에 호출할 수 없음) ) , 잠정적으로 '정상'으로 간주되지만, 아래 논의에 따르면 실제로는 삭제할 수 없는 속성을 삭제하는 반면 이전 브라우저에서는 삭제되지 않습니다.):

코드 복사 코드는 다음과 같습니다:

/* 'alert'는 'window'의 직접적인 속성입니다('hasOwnProperty를 믿을 수 있는 경우). ') */
window.hasOwnProperty('alert') // true

window.alert 삭제; // true
window.alert 유형 // "함수"

window.alert를 삭제하면 이 결과를 생성하는 속성이 없지만 true를 반환합니다(위 알고리즘에 따라). 참조로 확인되므로 첫 번째 단계에서는 true를 반환할 수 없습니다. 따라서 두 번째 단계에서는 true를 반환할 수 없습니다. true를 반환할 수 있는 유일한 방법은 알고리즘이 마지막 단계에 도달하여 실제로 속성을 삭제했지만 실제로는 삭제되지 않은 경우입니다. (번역자 주: 아니요, 오페라와 사파리에서는 실제로 삭제되었습니다...).

그래서 이 이야기는 호스트 개체를 절대 신뢰하지 말라고 말합니다.

7. ES5 엄격 모드 | ES5 엄격 모드

그렇다면 엄격 모드에서는 ECMAScript 버전 5에 어떤 기능이 추가되나요? 이러한 제한 사항 중 일부는 현재 설명되어 있습니다. 삭제 작업이 변수/함수 매개변수/함수 선언에 대한 직접 참조를 가리키는 경우 SyntaxError가 발생합니다. 또한 속성에 내부 속성 [[Configurable]] == false가 있는 경우 TypeError가 발생합니다.

코드 복사 코드는 다음과 같습니다.

(function(foo) {
"use strict "; //함수에서 엄격 모드를 활성화합니다.

var bar;
function baz;
delete foo; // 함수 매개변수 삭제 시 SyntaxError
delete bar; // 변수 삭제 시 SyntaxError
delete baz; , 함수 선언으로 생성된 변수를 삭제할 때

/* 함수 인스턴스의 길이는 [[Configurable]]입니다: false */
delete (function() {}).length; // TypeError
}) ();

또한 엄격 모드에서 선언되지 않은 변수(즉, 해결되지 않은 참조)를 삭제하면 SyntaxError가 발생하며, 동일한 모드에서 선언되지 않은 할당도 예외가 발생합니다(ReferenceError ).

코드 복사 코드는 다음과 같습니다.

"use strict";
삭제 i_dont_exist; // / 구문 오류
i_dont_exist_either = 1; // 참조 오류

이전에 제공된 변수, 함수 선언 및 매개변수의 예를 살펴본 후 이제 이러한 모든 제한 사항에 의미가 있다는 것을 이해하셨으리라 믿습니다. 엄격 모드는 이러한 문제를 단순히 무시하는 것이 아니라 보다 적극적이고 설명적인 접근 방식을 취합니다.

8. 요약 요약

이 글은 이미 꽤 길기 때문에 다른 내용(예: 삭제를 통한 배열 항목 삭제 및 그 효과)에 대해서는 다루지 않겠습니다. MDC/MDN에서 기사를 확인하거나 사양을 읽고 직접 테스트해 볼 수 있습니다.

Javascript에서 삭제가 작동하는 방식에 대한 간단한 요약은 다음과 같습니다.

•변수 및 함수 선언은 활성화 전역 개체의 속성입니다.
•속성에는 내부 속성이 있으며, 그 중 하나인 DontDelete는 속성 삭제 가능 여부를 결정하는 역할을 담당합니다.
•전역 코드 또는 함수 코드의 변수 및 함수 선언은 DontDelete를 사용하여 속성을 생성합니다.
•함수 매개변수도 활성화 객체의 속성이며 DontDelete를 갖습니다.
•Eval 코드의 변수 및 함수 선언은 DontDelete 없이 속성을 생성합니다.
• 선언되지 않은 새로운 속성은 빈 내부 속성으로 생성되므로 DontDelete가 없습니다.
•호스트 개체는 원하는 방식으로 삭제 프로세스에 응답할 수 있습니다.

원문: 삭제 이해번역: javascript에서 삭제번역: justjavac

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.