"use strict"

最近のモダンな JavaScript では、必ず

"use strict"

というのが書かれていると思います。この使い方を雰囲気ではわかってるけど、正しく理解していない場合が自分も含めて多いと思ったので書きとめたいと思います。

ちなみに、"use strict" でググると Perl のそれが出てきますが、Perl の話はしません。あとセミコロンの話もしません。

"use strict"とはそもそもなにか

"use strict" は、Use Strict Directive と呼ばれています。 これは ECMA-262 の 14.1 Directive Prologues and the Use Strict Directive によって示されています。

A Use Strict Directive is an ExpressionStatement in a Directive Prologue whose StringLiteral is either the exact character sequences "use strict" or 'use strict'. A Use Strict Directive may not contain an EscapeSequence or LineContinuation.

つまり、Directive Prologue のなかの ExpressionStatement で、その StringLiteral が完全に "use strict"'use strict' に一致するもの、という事ですね。エスケープとか入ってちゃダメよ、とも書いてあります。

じゃあ Directive Prologue とは、となります。それは ECMA-262 の同じセクションで示されています。

A Directive Prologue is the longest sequence of ExpressionStatement productions occurring as the initial SourceElement productions of a Program or FunctionBody and where each ExpressionStatement in the sequence consists entirely of a StringLiteral token followed a semicolon. The semicolon may appear explicitly or may be inserted by automatic semicolon insertion. A Directive Prologue may be an empty sequence.

第二文はみんな大好きセミコロンの話なので横においておくと、この無茶苦茶に長い第一文が Directive Prologue とは何かについて語っています。で、長いのですが注意深く読むと、プログラムや関数の最初に連続して現れる文字列たちのことだとわかります。

"use strict"の例

つまり、各々のプログラムや、関数なかの最初にある複数ありうる文字列の中で "use strict"'use strict' に完全に一致する文字列が Use Strict Directive となります。ということは次のような例が挙げられます。

  1. プログラムの先頭にある

     "use strict" // Use Strict Directive
     var a = 1
     …
    
  2. 関係ない文字列があってもOK

     "use puni puni"
     "use strict" // Use Strict Directive
     var a = 1
     ...
    
  3. コメントがあっても、スペースがあってもOK

     // Comment
         "use strict" // Use Strict Directive
     var a = 1
     ...
    
  4. FunctionBody の中でもOK

     function f() {
         "use strict"
         var a = 1
         ...
     }
    
  5. でもこれはダメ

     var a = 1
     "use strict" // NOT Use Strict Directive
     ...
    
  6. こういうのもダメ

     "us\145 strict" // NOT Use Strict Directive
     var a = 1
     ...
    

"use strict"があるとどうなるのか

Use Strict Directive があると、ECMA-262 の 10.1.1 Strict Mode Code に記載のある通り、文法が Strict Mode になります。ふんわか解釈するとこんな感じです。

  • Global code is strict global code if it begins with a Directive Prologue that contains a Use Strict Directive (see 14.1).

プログラムの先頭の Directive PrologueUse Strict Directive があればそのコード全体が Strict Mode になります。

  • Eval code is strict eval code if it begins with a Directive Prologue that contains a Use Strict Directive or if the call to eval is a direct call (see 15.1.2.1.1) to the eval function that is contained in strict mode code.

eval のコードの先頭の Directive PrologueUse Strict Directive があるか、Strict Mode のコードから直接呼び出される eval のコードは Strict Mode になります。

  • Function code that is part of a FunctionDeclaration, FunctionExpression, or accessor PropertyAssignment is strict function code if its FunctionDeclaration, FunctionExpression, or PropertyAssignment is contained in strict mode code or if the function code begins with a Directive Prologue that contains a Use Strict Directive.
  • Function code that is supplied as the last argument to the built-in Function constructor is strict function code if the last argument is a String that when processed as a FunctionBody begins with a Directive Prologue that contains a Use Strict Directive.

関数のコードの先頭の Directive PrologueUse Strict Directive があればその関数全体が Strict Mode になります。あるいは、その関数を定義する場所が Strict Mode であればその場合も Strict Mode になります。

"use strict"の意地悪な例

"use strict" の含まれるコードや eval の中身、関数の中身はその全体が Strict Mode になるところがポイントです。 ですので、わりと稀有なというかかなり意地悪な例としてはこんなのが考えられます。

    "us\145 puni puni"
    "use strict" // Use Strict Directive
    var a = 1
    ...

まずプログラムの先頭の文字列たちのなかにあるので、"use strict" は正しい Use Strict Directive です。ですのでコード全体が Strict Mode になります。 しかし Strict Mode では文字列中での \nnn による8進数のエスケープは許されませんから、1行目の \145 は SyntaxError です。ということで以下のありがちな思い込みは誤りです。

最近一部で有名なあの言語のソースでも誤って使われていたりするので気をつけましょう。 これは Strict Mode な気分でコード書いてんねんで、っていう意思表示には十分ですが、機能していません。

"use strict"があるとどうなるのか

手抜きなのですが、ECMA-262 の Annex C - The Strict Mode of ECMAScript に詳しいです。全部列挙するのは大変なので原文に目をお通しください。


間違いや typo の指摘やアドバイスは @niw まで是非!

では、"use strict" を使って楽しい JavaScript ライフを!