co to jest „tryb ścisły” i jak jest używany?

134

Przeglądałem referencje JavaScript w Mozilla Developer Network i natknąłem się na coś, co nazywa się "strict mode". Przeczytałem go ponownie i nie rozumiem, co robi. Czy ktoś może pokrótce wyjaśnić (ogólnie), jaki jest jego cel i do czego jest przydatny?

nkcmr
źródło
2
Związane z: stackoverflow.com/q/1335851/1461424
sampathsris

Odpowiedzi:

149

Jego głównym celem jest dokładniejsze sprawdzanie.

Po prostu dodaj "use strict";na górze kodu, zanim cokolwiek innego.

Na przykład, blah = 33;to poprawny JavaScript. Oznacza to, że tworzysz całkowicie globalną zmienną blah.

Ale w trybie ścisłym jest to błąd, ponieważ nie użyłeś słowa kluczowego "var" do zadeklarowania zmiennej.

Przez większość czasu nie masz na myśli tworzenia zmiennych globalnych w środku jakiegoś dowolnego zakresu, więc przez większość czasu, gdy blah = 33jest to napisane, jest to błąd, a programista tak naprawdę nie chciał, aby była to zmienna globalna, mieli na myśli pisać var blah = 33.

Podobnie zabrania wielu rzeczy, które są technicznie ważne. NaN = "lol"nie powoduje błędu. Nie zmienia też wartości NaN. używanie ścisłego this (i podobnych dziwnych stwierdzeń) powoduje błędy. Większość ludzi to docenia, ponieważ nie ma powodu, aby kiedykolwiek pisaćNaN = "lol" , więc najprawdopodobniej była to literówka.

Przeczytaj więcej na stronie MDN o trybie ścisłym

Simon Sarris
źródło
4
jest to dokładna
kopia
23
Czego więc nie rozumiesz na temat jego użyteczności? Ma na celu pomoc w rozwoju poprzez wyłapywanie rzeczy, które są prawidłowe, ale najbardziej prawdopodobne są błędy.
Simon Sarris,
34

Jednym z aspektów trybie ścisłym nie wspomniano w odpowiedzi Simona jest to, że ścisłe ustawia tryb thisna undefinedfunkcje wywoływane przez wywołania funkcji.

Więc takie rzeczy

function Obj() {
   this.a = 12;
   this.b = "a";
   this.privilegedMethod = function () {
      this.a++;
      privateMethod();
   };

   function privateMethod() {
     this.b = "foo";
   }
}

spowoduje błąd, gdy privateMethodzostanie wywołany (ponieważ nie możesz dodać właściwości do undefined), zamiast bezużytecznie dodawać bwłaściwość do obiektu globalnego.

Adam Rackis
źródło
4
tak, muszę dodać privateMethod.bind(this)();i new jsbin.com
sprawdzić
Najważniejsze ograniczenia w trybie ścisłym: docs.microsoft.com/en-us/scripting/javascript/advanced/…
Krishna Mohan
21

Dodano tryb ścisły, aby istniał łatwo analizowalny statycznie podzbiór EcmaScript, który byłby dobrym celem dla przyszłych wersji języka. Tryb ścisły został również zaprojektowany w nadziei, że programiści, którzy ograniczą się do trybu ścisłego, popełnią mniej błędów, a błędy, które robią, będą się manifestować w bardziej oczywisty sposób.

Harmony , która, miejmy nadzieję, stanie się następną główną wersją EcmaScript, zostanie zbudowana na bazie ES5rict.

Harmony opiera się na trybie ścisłym ES5, aby uniknąć zbyt wielu trybów.

Niektóre inne eksperymenty językowe również zależą od trybu ścisłego. SES zależy od możliwości analizy trybu ścisłego ES5.

Eksperyment projektowy SES (Secure ECMAScript)

Zaprojektuj język programowania Object Capability, usuwając lub naprawiając funkcje w ES5 / Strict.

Powinno istnieć bezpośrednie tłumaczenie z SES na ES5 / Strict.

Załącznik C normy wyjaśnia różnice między trybem ścisłym a trybem normalnym.

Ograniczenia i wyjątki trybu ścisłego

  • Identyfikatory „implements”, „interface”, „let”, „package”, „private”, „protected”, „public”, „static” i „yield” są klasyfikowane jako tokeny FutureReservedWord w ramach kodu trybu ścisłego. (7.6.12 [?]).
  • Zgodna implementacja podczas przetwarzania kodu trybu ścisłego nie może rozszerzać składni NumericLiteral (7.8.3) tak, aby obejmowała OctalIntegerLiteral, jak opisano w B.1.1.
  • Zgodna implementacja, podczas przetwarzania kodu trybu ścisłego (patrz 10.1.1), nie może rozszerzać składni EscapeSequence tak, aby obejmowała OctalEscapeSequence, jak opisano w B.1.2.
  • Przypisanie do niezadeklarowanego identyfikatora lub w inny sposób nierozwiązywalne odwołanie nie tworzy właściwości w obiekcie globalnym. Gdy proste przypisanie występuje w kodzie trybu ścisłego, jego LeftHandSide nie może oceniać jako nierozwiązywalnego odwołania. Jeśli tak, generowany jest wyjątek ReferenceError (8.7.2). LeftHandSide nie może również być odwołaniem do właściwości danych o wartości atrybutu {[[Writable]]: false}, do właściwości metody dostępu z wartością atrybutu {[[Set]]: undefined} ani do nieistniejącej właściwość obiektu, którego właściwość wewnętrzna [[Extensible]] ma wartość false. W takich przypadkach generowany jest wyjątek TypeError (11.13.1).
  • Identyfikator eval lub argumenty mogą nie pojawiać się jako LeftHandSideExpression operatora przypisania (11.13) lub PostfixExpression (11.3) lub jako UnaryExpression obsługiwany przez operatora Prefiks Increment (11.4.4) lub Prefix Decrement (11.4.5) . Obiekty argumentów dla funkcji trybu ścisłego definiują właściwości dostępu, których nie można konfigurować o nazwach „caller” i „callee”, które generują wyjątek TypeError przy dostępie (10.6).
  • Obiekty argumentów dla funkcji trybu ścisłego nie współużytkują dynamicznie swoich indeksowanych w tablicy wartości właściwości z odpowiednimi formalnymi powiązaniami parametrów ich funkcji. (10,6). W przypadku funkcji trybu ścisłego, jeśli zostanie utworzony obiekt argumentów, powiązanie argumentów lokalnego identyfikatora z obiektem arguments jest niezmienne i dlatego może nie być celem wyrażenia przypisania. (10,5).
  • Jest to błąd SyntaxError, jeśli kod trybu ścisłego zawiera ObjectLiteral z więcej niż jedną definicją dowolnej właściwości danych (11.1.5). Jest to błąd SyntaxError, jeśli identyfikator „eval” lub „argumenty” identyfikatora występują jako identyfikator w PropertySetParameterList elementu PropertyAssignment, który jest zawarty w ścisłym kodzie lub jeśli jego FunctionBody jest kodem ścisłym (11.1.5).
  • Kod eval trybu ścisłego nie może tworzyć instancji zmiennych ani funkcji w środowisku zmiennych obiektu wywołującego funkcję eval. Zamiast tego tworzone jest nowe środowisko zmiennych, które jest używane do tworzenia wystąpienia powiązań deklaracji dla kodu eval (10.4.2).
  • Jeśli jest to oceniane w ramach kodu trybu ścisłego, wartość ta nie jest przekształcana w obiekt. Wartość null lub undefined nie jest konwertowana na obiekt globalny, a wartości pierwotne nie są konwertowane na obiekty opakowania. Wartość ta przekazywana przez wywołanie funkcji (w tym wywołania wykonane przy użyciu funkcji Function.prototype.apply i Function.prototype.call) nie wymusza przekazywania tej wartości do obiektu (10.4.3, 11.1.1, 15.3.4.3, 15.3. 4.4).
  • Gdy operator usuwania występuje w kodzie trybu ścisłego, generowany jest błąd SyntaxError, jeśli jego UnaryExpression jest bezpośrednim odniesieniem do zmiennej, argumentu funkcji lub nazwy funkcji (11.4.1).
  • Gdy operator usuwania występuje w kodzie trybu ścisłego, generowany jest błąd TypeError, jeśli usuwana właściwość ma atrybut {[[Configurable]]: false} (11.4.1). Jest to SyntaxError, jeśli VariableDeclaration lub VariableDeclarationNoIn występuje w ścisłym kodzie, a jego identyfikatorem jest eval lub arguments (12.2.1).
  • Kod trybu ścisłego może nie zawierać WithStatement. Wystąpienie WithStatement w takim kontekście to SyntaxError (12.10).
  • Jest to SyntaxError, jeśli TryStatement z Catch występuje w ścisłym kodzie, a Identyfikatorem produkcji Catch jest eval lub argumenty (12.14.1)
  • Jest to SyntaxError, jeśli identyfikator eval lub argumenty pojawia się w FormalParameterList trybu ścisłego FunctionDeclaration lub FunctionExpression (13.1)
  • Funkcja trybu ścisłego nie może mieć dwóch lub więcej parametrów formalnych o tej samej nazwie. Próba utworzenia takiej funkcji przy użyciu konstruktora FunctionDeclaration, FunctionExpression lub Function to SyntaxError (13.1, 15.3.2).
  • Implementacja nie może rozszerzać poza to, co zdefiniowano w tej specyfikacji, znaczeń w ramach funkcji trybu ścisłego właściwości nazwanych wywołującym lub argumentów instancji funkcji. Kod ECMAScript nie może tworzyć ani modyfikować właściwości z tymi nazwami w obiektach funkcji, które odpowiadają funkcjom trybu ścisłego (10.6, 13.2, 15.3.4.5.3).
  • Elementem SyntaxError jest użycie w kodzie trybu ścisłego identyfikatorów eval lub argumentów jako identyfikatora deklaracji funkcji lub wyrażenia funkcji lub jako formalnej nazwy parametru (13.1). Próba dynamicznego zdefiniowania takiej funkcji trybu ścisłego za pomocą konstruktora Function (15.3.2) spowoduje zgłoszenie wyjątku SyntaxError.
Mike Samuel
źródło
6

ECMAScript 5 wprowadził koncepcję trybu ścisłego .

Wywołanie trybu ścisłego w kodzie

Tryb ścisły dotyczy całych skryptów lub poszczególnych funkcji. Nie dotyczy instrukcji blokowej ujętej w nawiasy {}, próba zastosowania jej w takich kontekstach nic nie daje.

Cały skrypt:

Powiedzmy, że tworzymy app.js, więc dodanie skryptu użycia pierwszej instrukcji wymusi tryb ścisły dla całego kodu.

// app.js whole script in strict mode syntax
use strict”;
// Now you can start writing your code 

Tryb ścisły dla funkcji:

Aby wywołać tryb ścisły dla funkcji, umieść dokładną instrukcję „użyj ścisłego”; na początku treści funkcji przed jakąkolwiek inną instrukcją.

function yourFunc(){
 "use strict";

 // Your function code logic
}

Tryb ścisły obejmuje kilka zmian w normalnej semantyce Javascript. Pierwszy tryb ścisły eliminuje niektóre ciche błędy JavaScript, zmieniając je tak, aby wyświetlały błędy.

Na przykład: kod w trybie ścisłym

wprowadź opis obrazu tutaj

W powyższym przykładzie kodu bez użycia trybu ścisłego w kodzie Nie spowoduje to błędu. Ponieważ mamy dostęp do zmiennej xbez jej deklarowania. Więc w trybie ścisłym dostęp do niezadeklarowanej zmiennej generuje błąd.

Teraz spróbujmy uzyskać dostęp do zmiennej x bez deklarowania jej bez trybu ścisłego.

(function(){
    x = 3;
})();

// Will not throw an error

Zaleta korzystania z trybu ścisłego:

  • Wyeliminuj ciche błędy JavaScript, zgłaszając błąd.
  • Naprawia błąd, który utrudnia silnikowi JavaScript wykonywanie optymalizacji.
  • Czasami kod działa szybciej niż identyczny kod, który nie jest w trybie ścisłym
  • Zabrania niektórych składni, które prawdopodobnie zostaną zdefiniowane w przyszłej wersji ECMAScript.
Nishant Kumar
źródło
5

Tryb ścisły wprowadza kilka zmian w normalnej semantyce JavaScript.

  • Tryb ścisły eliminuje niektóre ciche błędy JavaScript, zmieniając je tak, aby wyświetlały błędy.

  • Tryb ścisły naprawia błędy, które utrudniają silnikom JavaScript wykonywanie optymalizacji.

  • tryb ścisły zabrania niektórych składni, które prawdopodobnie zostaną zdefiniowane w przyszłych wersjach ECMAScript.

Renganathan MG
źródło
1

ECMAScript5 wprowadza kilka nowych obiektów i właściwości a także tzw "strict mode" .

Tryb ścisły to podzbiór języka, który wyklucza przestarzałe funkcje. Tryb ścisły to opt-in i nie jest wymagany, co oznacza, że ​​jeśli chcesz, aby kod działał w trybie ścisłym, deklarujesz swój zamiar, używając (raz na funkcję lub raz na cały program) następującego ciągu:

"use strict";
Vahid Hallaji
źródło
1

2017 iw końcu znalazłem dokumentację:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode

Tryb ścisły to sposób na włączenie ograniczonej wersji języka JavaScript. Tryb ścisły to nie tylko podzbiór: celowo ma inną semantykę niż normalny kod. Przeglądarki, które nie obsługują trybu ścisłego, będą uruchamiać kod trybu ścisłego zachowując się inaczej niż przeglądarki, które to robią, więc nie należy polegać na trybie ścisłym bez testowania funkcji w celu obsługi odpowiednich aspektów trybu ścisłego. Kod trybu ścisłego i kod trybu nieostrego mogą współistnieć, więc skrypty mogą włączać tryb ścisły przyrostowo.


Tryb ścisły wprowadza kilka zmian w normalnej semantyce JavaScript. Po pierwsze, tryb ścisły eliminuje niektóre ciche błędy JavaScript, zmieniając je tak, aby wyświetlały błędy. Po drugie, tryb ścisły naprawia błędy, które utrudniają silnikom JavaScript wykonywanie optymalizacji: kod w trybie ścisłym może czasami działać szybciej niż identyczny kod, który nie jest trybem ścisłym. Po trzecie, tryb ścisły zabrania niektórych składni, które prawdopodobnie zostaną zdefiniowane w przyszłych wersjach ECMAScript.

Tilak Maddy
źródło
0

Pytanie:
Oto problem, który napotkałem, postępowałem zgodnie z tutorialem i skończyło się na tym, że próbowałem skompilować następujący scssplik i próbowałem wygenerować z niego kod CSS,

.fatty{
  width: percentage(6/7);
}

za pomocą następującego gulpfile.jszadania:

var gulp = require('gulp');
var sass = require('gulp-sass');

gulp.task('sass', function () {
    return gulp.src('app/scss/styles.scss')
        .pipe(sass())
        .pipe(gulp.dest('app/css'))
});

Więc otrzymuję następujący błąd:

~/htdocs/Learning/gulp1/node_modules/gulp-sass/index.js:66
    let sassMap;
    ^^^

SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:373:25)
// stacktrace here...

Rozwiązanie:
Pokazuje więc index.jsplik, który znajduje się w moim module gulp-sass (który jest w zasadzie zablokowany i nie powinien być edytowany). Ale jeśli pójdę na siłę i dodam "use_strict"na początku tego index.jspliku, moje zadanie będzie przebiegać sprawnie.

Byłem bezradny, więc nadal używam tego jako rozwiązania! Ale potem, po przejrzeniu kilku innych pytań i odpowiedzi SO , zobaczyłem następującą odpowiedź :

sudo npm install -g n
sudo n stable

i wcześniej zaktualizowałem moje NodeJ (do wersji 10.x), a następnie przebudowałem Gulp, uruchamiając następujące polecenia zgodnie z instrukcjami Terminal:

npm rebuild node-sass --force

I wszystko w porządku. Więc tak to zostało rozwiązane. Cofnąłem zmiany, które wprowadziłem dla index.jspliku modułu gulp. A teraz działa płynnie.

Mam nadzieję, że ta odpowiedź będzie pomocna dla kogoś tam!

Randika Vishman
źródło