[javascript] JavaScript에서 “엄격한 사용”은 무엇을하며 그 이유는 무엇입니까?

최근에 Crockford의 JSLint를 통해 일부 JavaScript 코드를 실행 했으며 다음 오류가 발생했습니다.

1 행의 문제점 문자 1 : “엄격한 사용”명령문이 누락되었습니다.

일부 검색을 수행하면 일부 사람들 "use strict";이 JavaScript 코드에 추가한다는 것을 깨달았습니다 . 문을 추가하면 오류가 더 이상 나타나지 않습니다. 불행히도 구글은이 문자열 진술의 역사를 많이 밝히지 않았다. 확실히 브라우저가 JavaScript를 해석하는 방법과 관련이 있어야하지만 그 효과가 무엇인지 모르겠습니다.

그렇다면 무엇을 "use strict";의미하고 무엇을 의미하며 여전히 관련이 있습니까?

현재 브라우저 중 하나가 "use strict";문자열에 응답 합니까 아니면 나중에 사용할 수 있습니까?



답변

Javascript Strict Mode에 대한이 기사는 다음과 같습니다. John Resig-ECMAScript 5 Strict Mode, JSON 등

흥미로운 부분을 인용하려면 :

엄격 모드는 ECMAScript 5의 새로운 기능으로 “엄격한”운영 컨텍스트에 프로그램 또는 기능을 배치 할 수 있습니다. 이 엄격한 컨텍스트는 특정 조치가 수행되지 않도록하고 더 많은 예외를 발생시킵니다.

과:

엄격한 모드는 몇 가지 방법으로 도움이됩니다.

  • 일반적인 코딩 블로커를 잡아 예외를 던집니다.
  • 상대적으로 “안전하지 않은”조치가 수행 될 때 (예 : 글로벌 오브젝트에 대한 액세스 권한 확보) 오류를 방지하거나 발생시킵니다.
  • 혼란 스럽거나 잘못 생각한 기능을 비활성화합니다.

또한 전체 파일에 “엄격 모드”를 적용 할 수 있습니다 … 또는 특정 기능 (여전히 John Resig의 기사에서 인용) 에만 사용할 수 있습니다 .

// Non-strict code...

(function(){
  "use strict";

  // Define your library strictly...
})();

// Non-strict code... 

이전 코드와 새 코드를 혼합 해야하는 경우 도움이 될 수 있습니다. 😉

그래서 나는 그것이 "use strict"Perl에서 사용할 수있는 것과 약간 비슷하다고 생각합니다 (따라서 이름은 무엇입니까?) .

엄격한 모드는 이제 모든 주요 브라우저에서 지원됩니다 .

내부 네이티브 인 ECMAScript 모듈 (과 importexport문)와 ES6 클래스 , 엄격 모드는 항상 활성화 및 비활성화 할 수 없습니다.


답변

ECMAScript 5의 새로운 기능입니다. John Resig는 이에 대한 훌륭한 요약 을 작성했습니다.

JavaScript 파일 (파일 상단 또는 함수 내부)에 넣은 문자열입니다.

"use strict";

코드에 넣는 것은 문자열 일뿐이므로 현재 브라우저에서 문제를 일으키지 않아야합니다. 코드가 pragma를 위반하면 나중에 코드에 문제가 발생할 수 있습니다. 예를 들어, 현재 foo = "bar"정의하지 않고 있다면 foo코드가 실패하기 시작합니다. 제 생각에는 좋은 것입니다.


답변

이 명령문 "use strict";은 브라우저가 엄격하고 안전한 JavaScript 기능 세트 인 엄격 모드를 사용하도록 지시합니다.

기능 목록 (완전하지 않음)

  1. 전역 변수를 허용하지 않습니다. ( var변수 이름에 누락 된 선언 및 오타가 있음)

  2. 자동 실패 할당은 엄격 모드 (할당 NaN = 5;) 에서 오류를 발생시킵니다.

  3. 삭제 불가능한 속성을 삭제하려고하면 ( delete Object.prototype)

  4. 객체 리터럴의 모든 속성 이름은 고유해야합니다 ( var x = {x1: "1", x1: "2"}).

  5. 함수 매개 변수 이름은 고유해야합니다 ( function sum (x, x) {...})

  6. 8 진수 구문을 금지합니다 ( var x = 023;일부 개발자는 앞의 0이 숫자를 변경하는 데 아무 것도 없다고 잘못 가정합니다.)

  7. with키워드를 금지합니다

  8. eval 엄격 모드에서는 새로운 변수를 도입하지 않습니다

  9. 일반 이름 삭제 금지 ( delete x;)

  10. 할당 이름의 또는 바인딩을 금지 eval하고 arguments어떤 형태

  11. 엄격 모드는 arguments공식 매개 변수 를 사용하여 오브젝트의 특성에 별명을 지정하지 않습니다 . (즉, function sum (a,b) { return arguments[0] + b;}이것은 arguments[0]묶여 있기 때문에 작동 a합니다.)

  12. arguments.callee 지원되지 않습니다

[참고 : 엄격 모드 , Mozilla 개발자 네트워크 ]


답변

사람들이 사용에 대해 걱정한다면 use strict이 기사를 확인하는 것이 좋습니다.

브라우저에서 ECMAScript 5 ‘엄격한 모드’지원. 이것은 무엇을 의미 하는가?
NovoGeek.com-Krishna의 웹 로그

브라우저 지원에 대해 이야기하지만 더 중요하게는 브라우저를 안전하게 처리하는 방법에 대해 설명합니다.

function isStrictMode(){
    return !this;
}
/*
   returns false, since 'this' refers to global object and
   '!this' becomes false
*/

function isStrictMode(){
    "use strict";
    return !this;
}
/*
   returns true, since in strict mode the keyword 'this'
   does not refer to global object, unlike traditional JS.
   So here, 'this' is 'undefined' and '!this' becomes true.
*/


답변

주의해야 할 것은 하드 충전 프로그래머 모두입니다. "use strict"기존 코드에 적용 하면 위험 할 수 있습니다! 이 것은 기분이 좋고 행복한 얼굴 스티커가 아니므로 코드를 더 잘 찍을 수 있습니다. 로 "use strict"프라 그마, 브라우저가 갑자기 기본 / 느슨한 자바 스크립트를 행복하게 수 있다는 그 자리에 당신이 뭔가를하고있는 이유만으로 그 전에 던졌다 결코 임의의 장소에서 예외가 있지만, 엄격한 자바 스크립트 혐오가 발생합니다! 엄격하게 위반하면 코드에서 거의 사용되지 않는 호출에 숨겨져있어 결국 유료 고객이 사용하는 프로덕션 환경에서 예외가 발생할 수 있습니다.

급락을하려는 경우 "use strict"포괄적 인 단위 테스트와 엄격하게 구성된 JSHint 빌드 작업을 함께 적용 하여 모듈의 어두운 구석이 없다는 사실을 확신 할 수 있습니다. 엄격 모드를 켰습니다. 또는 다른 옵션 "use strict"이 있습니다. 레거시 코드에 추가하지 마십시오 . 정직하게 더 안전 할 것입니다. 타사 모듈과 같이 소유하거나 유지 관리하지 않는 모듈에는 추가 하지 마십시오"use strict" .

나는 그것이 갇힌 동물 "use strict"이지만 좋은 물건이 될 수 있다고 생각하지만 , 당신은 올바르게해야합니다. 엄격하게 가기 가장 좋은시기는 프로젝트가 그린 필드이고 처음부터 시작할 때입니다. 구성 JSHint/JSLint의 모든 경고 및 옵션은 당신의 팀이, 위 같은 금일 조작 된 좋은 빌드 / 테스트 / 어설 션 시스템을 얻을 수있는 꽉으로 최대 마약 Grunt+Karma+Chai, 오직 그때 모든 새 모듈을 표시 시작합니다 "use strict". 많은 오류와 경고를 치료할 수 있도록 준비하십시오. JSHint/JSLint위반이 발생할 경우 빌드를 FAIL로 구성하여 모든 사람이 중력을 이해하도록하십시오 .

내가 채택했을 때 내 프로젝트는 그린 필드 프로젝트가 아니었다 "use strict". 결과적으로 "use strict"모듈의 절반 이 없기 때문에 IDE에 빨간색 표시가 생겨 JSHint가 이에 대해 불평합니다. 앞으로 리팩토링을 어떻게해야하는지 상기시켜줍니다. 나의 목표는 모든 누락 된 "use strict"진술 로 인해 빨간색 표시가없는 것이지만 지금은 몇 년이 지났습니다.


답변

을 사용해도 'use strict';코드가 갑자기 나아지는 것은 아닙니다.

자바 스크립트 엄격 모드는 기능입니다 인 ECMAScript 5 . 스크립트 / 함수 맨 위에 이것을 선언하여 엄격 모드를 활성화 할 수 있습니다.

'use strict';

JavaScript 엔진이이 지시문을 보면 특수 모드에서 코드를 해석하기 시작합니다. 이 모드에서는 잠재적 인 버그가 될 수있는 특정 코딩 방법이 감지 될 때 오류가 발생합니다 (엄격 모드의 원인).

이 예제를 고려하십시오.

var a = 365;
var b = 030;

숫자 리터럴을 정렬하는 것에 대한 집착으로 개발자는 실수로 변수 b를 8 진 리터럴 로 초기화했습니다 . 엄격하지 않은 모드는이 값을 2410을 기준 으로 값이있는 숫자 리터럴로 해석합니다 . 그러나 엄격 모드에서는 오류가 발생합니다.

엄격 모드의 비전문가 목록은 이 답변을 참조하십시오 .


어디에서 사용해야 'use strict';합니까?

  • 내에서 새로운 자바 스크립트 응용 프로그램 : 물론! 엄격한 모드는 코드로 바보 같은 일을 할 때 내부 고발자로서 사용될 수 있습니다.

  • 내에서 기존의 자바 스크립트 코드 : 아마 아닙니다! 기존 JavaScript 코드에 엄격 모드에서 금지 된 명령문이있는 경우 애플리케이션이 중단됩니다. 엄격 모드를 원하면 기존 코드를 디버그하고 수정할 준비가되어 있어야합니다. 이것이 사용 'use strict';이 갑자기 코드를 향상시키지 않는 이유 입니다.


엄격 모드는 어떻게 사용합니까?

  1. 'use strict';스크립트 위에 문장을 삽입하십시오 .

    // File: myscript.js
    
    'use strict';
    var a = 2;
    ....

    파일의 모든 내용 myscript.js은 엄격 모드로 해석됩니다.

  2. 또는 'use strict';함수 본문 위에 명령문을 삽입 하십시오.

    function doSomething() {
        'use strict';
        ...
    }

    어휘 기능 범위 의 모든 내용은 doSomething엄격 모드에서 해석됩니다. 어휘 범위 라는 단어 가 여기서 중요합니다. 예를 들어, 엄격한 코드가 엄격 하지 않은 라이브러리의 함수를 호출하면 코드 만 호출 된 함수가 아닌 엄격 모드로 실행됩니다. 자세한 설명 은 이 답변 을 참조하십시오 .


엄격 모드에서 금지 된 사항은 무엇입니까?

엄격한 모드에서 금지 된 몇 가지 사항을 설명 하는 멋진 기사 를 찾았습니다 (이 목록은 독점 목록이 아닙니다).

범위

역사적으로 JavaScript는 함수의 범위를 지정하는 방법에 대해 혼란 스러웠습니다. 때로는 정적으로 범위가 지정된 것처럼 보이지만 일부 기능은 동적으로 범위가 지정된 것처럼 동작합니다. 혼란 스럽기 때문에 프로그램을 읽고 이해하기가 어렵습니다. 오해로 인해 버그가 발생합니다. 성능 문제이기도합니다. 정적 범위 지정은 컴파일 타임에 변수 바인딩이 발생하도록 허용하지만 동적 범위에 대한 요구 사항은 바인딩이 런타임으로 지연되어야한다는 것을 의미하며 이는 상당한 성능 저하가 따릅니다.

엄격 모드에서는 모든 변수 바인딩을 정적으로 수행해야합니다. 즉, 이전에 동적 바인딩이 필요한 기능을 제거하거나 수정해야합니다. 특히 with 문이 제거되고 호출자의 환경을 변경하는 eval 함수의 기능이 심각하게 제한됩니다.

엄격한 코드의 장점 중 하나는 YUI Compressor 와 같은 도구
가 처리 할 때 더 나은 작업을 수행 할 수 있다는 것입니다.

내재 된 글로벌 변수

JavaScript는 전역 변수를 암시했습니다. 변수를 명시 적으로 선언하지 않으면 전역 변수가 암시 적으로 선언됩니다. 이를 통해 초보자는 기본 하우스 키핑 작업을 무시할 수 있으므로 프로그래밍이 쉬워집니다. 그러나 큰 프로그램을 관리하기가 훨씬 어려워지고 안정성이 크게 저하됩니다. 따라서 엄격 모드에서는 내재 된 전역 변수가 더 이상 생성되지 않습니다. 모든 변수를 명시 적으로 선언해야합니다.

글로벌 누출

this
전역 객체에 바인딩 될 수있는 여러 상황이 있습니다 . 예를 들어 new생성자 함수를 호출 할 때 접두사 를 제공하지 않으면 생성자가 this전역 객체에 예기치 않게 바인딩되므로 새 객체를 초기화하는 대신 전역 변수가 자동으로 변경됩니다. 이러한 상황에서는 엄격 모드가 대신에 바인딩 this되어 undefined생성자가 대신 예외를 throw하여 오류를 훨씬 빨리 감지 할 수 있습니다.

시끄러운 실패

JavaScript에는 항상 읽기 전용 속성이 있었지만 ES5의 Object.createProperty
기능이 해당 기능을 노출 할 때까지 직접 만들 수 없었습니다 . 읽기 전용 속성에 값을 할당하려고하면 자동으로 실패합니다. 할당은 속성 값을 변경하지 않지만 프로그램은 마치 그대로 진행됩니다. 이는 프로그램이 일관성이없는 상태가 될 수있는 무결성 위험입니다. 엄격 모드에서는 읽기 전용 속성을 변경하려고하면 예외가 발생합니다.

옥탈

숫자의 8 진법 (또는 8 진법)은 단어 크기가 3의 배수 인 기계에서 기계 수준 프로그래밍을 수행 할 때 매우 유용했습니다. 단어 크기가 60 비트 인 CDC 6600 메인 프레임으로 작업 할 때는 8 진법이 필요했습니다. 8 진수를 읽을 수 있다면 단어를 20 자리로 볼 수 있습니다. 2 자리 숫자는 op 코드를 나타내고 1 자리 숫자는 8 개의 레지스터 중 하나를 나타냅니다. 기계어 코드에서 고급 언어로 느리게 전환하는 동안 프로그래밍 언어로 8 진 형식을 제공하는 것이 유용한 것으로 생각되었습니다.

C에서는 매우 불행한 8 진 표현이 선택되었습니다 : 선행 0. 따라서 C에서는 0100100이 아니라 64를 의미하며 088이 아닌 오류입니다. 더 불행하게도,이 구식은 오류를 만드는 데만 사용되는 JavaScript를 포함한 거의 모든 현대 언어로 복사되었습니다. 다른 목적은 없습니다. 따라서 엄격 모드에서는 8 진 형식이 더 이상 허용되지 않습니다.

등등

인수 의사 배열은 ES5에서 조금 더 배열과 비슷해집니다. 엄격 모드에서는 해당
속성 calleecaller속성 이 손실 됩니다. 이를 통해 arguments많은 기밀 컨텍스트를 포기하지 않고 신뢰할 수없는 코드 로 전달할 수 있습니다 . 또한 arguments기능 의
속성이 제거됩니다.

엄격 모드에서 함수 리터럴의 중복 키는 구문 오류를 생성합니다. 함수는 같은 이름을 가진 두 개의 매개 변수를 가질 수 없습니다. 함수는 매개 변수 중 하나와 이름이 같은 변수를 가질 수 없습니다. 함수는 delete자체 변수를 가질 수 없습니다 . delete구성 할 수없는 속성을 시도
하면 예외가 발생합니다. 기본 값은 암시 적으로 랩핑되지 않습니다.


향후 JavaScript 버전을위한 예약어

ECMAScript 5는 예약어 목록을 추가합니다. 변수 또는 인수로 사용하면 엄격 모드에서 오류가 발생합니다. 예약어는 다음과 같습니다.

implements, interface, let, package, private, protected, public, static, 및yield


추가 자료


답변

모든 개발자가 지금 엄격 모드를 사용하는 것이 좋습니다. 엄격한 모드는 코드에서 알지 못했던 오류로부터 합법적으로 우리를 구할 수 있도록 충분한 브라우저를 지원합니다.

분명히, 초기 단계에서 우리가 전에는 본 적이없는 오류가있을 것입니다. 모든 이점을 얻으려면 엄격한 모드로 전환 한 후 모든 것을 포착했는지 확인하기 위해 적절한 테스트를 수행해야합니다. 확실히 우리는 단지 use strict코드를 던지지 않고 오류가 없다고 가정합니다. 따라서 더 좋은 코드를 작성하기 위해이 매우 유용한 언어 기능을 사용하기 시작해야합니다.

예를 들어

var person = {
    name : 'xyz',
    position : 'abc',
    fullname : function () {  "use strict"; return this.name; }
};

JSLint 는 Douglas Crockford가 작성한 디버거입니다. 스크립트에 붙여 넣기 만하면 코드에서 눈에 띄는 문제와 오류가 있는지 신속하게 스캔합니다.