チャクラ。 相互運用性は単なる標準ではない

標準仕様の一部ではない機能を実装する決定はどのように行われますか? すべてのブラウザープロバイダーと同様に、多くの場合、この決定を下す必要があります。 この出版物は、標準仕様が十分でない場合に相互運用可能なブラウザーを作成するために使用されるいくつかの原則を説明するために、実際のJavaScriptの例を多数提供します。

理想的には、標準の仕様は自給自足です。 JavaScriptの実装には、ECMAScript仕様で指定されているすべてが含まれているだけで、それ以上は含まれてません。 ブラウザの相互運用性を確保するには、 Ecma InternationalW3Cなどの標準化組織によって公開さた仕様が不可欠であると考えています。 このような仕様は、ブラウザのエグゼクティブに実装すべき機能と、Webサイト開発者に使用すべき機能を伝えます。

インターネットの現実の世界では、物事はそれほど明確に定義されていません。 仕様が完全であることはめったになく、意図的に不完全またはあいまいなままになることもあります。 ES5仕様の編集者としての私たち自身の経験により、最終的な解決策を見つけられなかった問題が常にあると述べることができます。 その結果、標準仕様で定義されていない関数は広く実装され、適用されます。 既存のインターネット上で動作するブラウザを構築しようとする開発者は、標準の仕様でカバーされていない多くの機能を実装する必要があります。

実際の正規表現文法とは何ですか?


Chakraを作成する際、ECMAScript 5(ES5)仕様(正規表現の文法を含む)に注意深く従いました。 しかし、実際のWebサイトでテストを開始すると、一部の正規表現リテラルの構文エラーが原因で機能しなかったページが出始めました。 たとえば、次のような右角かっこを含む正規表現でクラッシュが発生しました。

next = /]/.exec(buffer);

その理由は、ECMAScript正規表現の文法が、一致する文字として直接使用できない文字のリストに含まれているためです。 仕様では、シンボル/]/無効である/]/ますが、代わりに/\]/を使用する必要があります。 文字に対するそのような制限は重要です。そうでなければ、 /axyz[ad]qwer/などのリテラルを解析することが不可能になるためです。 ただし、記号[が前に付かない単一の括弧]は、実際には分析の障害にはなりません。 ただし、この規格はまだ受け入れられないと主張しています。

実際には、すべてのブラウザーが/]/などの正規表現を受け入れ、Webサイト開発者がそれらを記述します。

コンセンサス関数とは、標準の一部ではないが、相互運用性を提供する方法で普遍的に実装されている関数を記述するために使用する用語です。 一般に、IE9およびその他のJavaScript実装には、実際のWebコンテンツを操作するためのこのようなコンセンサス関数を含める必要があります。 それらが標準の仕様に含まれていないため、本当の困難はそれらを識別することにあります。

私たちは、この種のコンセンサス機能を維持する必要性を認識しており、インターネットの関連規格の将来の版にそれらが含まれるように努力します。 ただし、すべてのJavaScript拡張機能が普遍的または均一に実装されているわけではありません。

IE9に名前に_ _文字を含むメソッドがないのはなぜですか?


ES5には、メソッドの読み取りと設定のサポートが含まれています。 一部のWebブラウザでは、長年にわたって同様の機能が利用可能です。 この期間中、ブラウザ開発者はさまざまな構文とアプリケーションプログラミングインターフェイス(API)を試し、そのようなメソッドを定義しました。 ES5より前は、最も広く実装されていたAPIは__defineGetter__および__defineSetter__という名前の2つのメソッドを使用して、読み取り/設定メソッドを定義していました。 メソッド名の両側でアンダースコアを使用することは、一部のブラウザ開発者が実験的な機能であるメソッドをマークしたり、特定のJavaScript実装の独自の低レベル機能にアクセスするために使用する記号です。

ECMA TC39メンバーは、利点が明らかであるため、ES5仕様に読み取りおよび設定方法を含めることに同意しました。 ただし、TC39委員会は、新しいAPIを作成してそれらを定義し、__ defineXXX__インターフェイスの標準化を控えることを決定しました。

TC39がこれを行ったのはなぜですか? このAPIを提供したブラウザーの動作に大きな違いがあるため。 これらのメソッドの一般的なセマンティクスに基づく標準化は、新しいセマンティクスに合わせて既存のブラウザー実装の一部またはすべてを変更する必要があることを意味します。 そして、これはおそらく、特定のブラウザで機能するように書かれたいくつかのアプリケーションを機能させないでしょう。

もう1つの理由は、命名規則の論理的整合性を維持することです。 ECMAScriptの他の埋め込み名は、アンダースコアで始まったり、アンダースコアで終わったりしません。 そのような名前と実験的な関数の接続、または特定の関数の実装は広く知られています。 標準化された関数にこのシンボルを使用すると誤解を招き、将来の実験での有用性が低下します。

TC39委員会は、 Object.definePropertyメソッドに基づいて新しいAPIを開発しました。 このインターフェイスは、読み取りおよび設定メソッドのプロパティの定義だけでなく、他の新しいES5機能もサポートします。 __DefineXXX__メソッドはES5仕様に含まれていませんでした。

__defineXXX__ APIが既に実装されているブラウザーは、互換性を確保するために、引き続き変更せずにサポートできます。 ただし、ES5標準をサポートするブラウザーの互換性を確保するために記述された新しいコードでは、Object.definePropertyメソッドを使用して、読み取りメソッドのプロパティを決定し、値を設定する必要があります。

開発チームはまだIE9に__defineXXX__プログラミングインターフェイスを追加するよう求められています。 理由は明らかです。 一部の開発者は、これらのインターフェイスを使用するコードを既に持っており、このコードをIE9で実行したいと考えています。 ただし、IE9開発者は、これらのインターフェイスをサポートすることは、インターネット上で相互運用性を提供するという基本的な利益にはならないと考えています。 TC39はすでにこのAPIをレビューしており、その標準化は望ましくないと結論付けています。 IE9で__defineXXX__インターフェイスのサポートが追加された場合、このAPIはインターネット上で恒久的なコンセンサス機能にさらに近づくでしょう。 これは基本的にTC39の決定をキャンセルします。

残念ながら、短期的には、これにより、この古いAPIを現在使用している開発者にとって、わずかな追加作業が発生します。 ただし、 Object.definePropertyメソッドを使用して__defineXXX__インターフェイスを実装する既存のコードの単純な互換性ライブラリを作成するのは簡単なことのように思えます。

手術不能コンセンサス機能


JavaScriptコードでは、関数へのリンクを設定できます。また、関数の宣言に先行するコードでリンクを呼び出すこともできます。 これは、JavaScriptがすべての関数宣言をコード本体の上部に論理的に「持ち上げる」ために可能です。 JavaScriptでは、同じ名前の複数の関数宣言も許可されます。 簡単なテスト機能を検討してください。

  <code> function testFuncDeclarationOrder(){</ code> 


  <code> f1(); </ code> 


  <code> function f1(){alert( "first f1")} </ code> 


  <code> </ code> <code> f1(); </ code> 


  <code> function f1(){alert( "second f1")} </ code> 


  <code> f1(); </ code> 


  <code>} </ code> 


呼び出し後、関数は一連のアラートを作成しました:「second f1」、「second f1」、「second f1」。 これは、JavaScriptが実際にこの関数を次のように記述されているかのように処理するためです。

  <code> function testFuncDeclarationOrder(){</ code> 


  <code> function f1(){alert( "first f1")} </ code> 


  <code> function f1(){alert( "second f1")} </ code> 


  <code> f1(); </ code> 


  <code> f1(); </ code> 


  <code> f1(); </ code> 


  <code>} </ code> 


ECMAScript仕様では、これまで、関数宣言の配置に1つの制限のみを課してきました。 ECMAScript標準には、制御構造内の命令の本体内に関数宣言を配置する機能は含まれていません。 以下にコード例を示します。

  <code> if(someCondition){</ code> 


  <code> function f1(){alert( "f1")} </ code> 


  <code>} </ code> 


ECMAScript仕様に従って解析する場合、上記のコードは構文エラーを引き起こします。 ただし、任意のブラウザーで実行すると、エラーは発生しないようです。 命令が許可されている場合はどこでも関数宣言のサポートは、インターネット上のコンセンサス関数です。 もしそうなら、なぜこれはES5に含まれていないのですか? ES5仕様のセクション12は、実際にこれについて何かを述べています。

一般的に使用されるいくつかのECMAScript実装が、命令としての関数宣言の使用をサポートすることが知られています。 ただし、実装間では、このような関数宣言に適用されるセマンティクスに重要かつ矛盾するバリエーションがあります。 これらの不一致の違いにより、関数宣言を命令として使用すると、実装間で確実に移植できないコードが生成されます。 ECMAScript実装では、このような関数宣言の使用を禁止するか、宣言に必須の警告を添付することをお勧めします。 ECMAScriptの将来のエディションでは、命令のコンテキストで関数を宣言するための代替のポータブル手段が定義される可能性があります。

これらの読めない製剤はどういう意味ですか? 簡単に言えば、異なるブラウザーの動作は大きく異なるため、調整の試みは非現実的でした。

IE9は何をしますか? IE9は、ES5仕様で推奨されているような関数の命令宣言を禁止していますか? いいえ、IE9では、このような広告は以前のバージョンのIEとまったく同じように処理されます。

なぜこの決定が下されたのですか? ブラウザー開発者による以前の実験では、このような広告を拒否すると、多くの既存のWebページが操作不能になることが示されているためです。

これはすごいようです。 Webページは、ブラウザごとに動作が異なる機能に依存しているにもかかわらず、ブラウザごとに互換性があるのでしょうか。 1つの可能な答え:実際には、コードは使用されません。 これは、呼び出されることのない関数でも、その結果がページの機能にとって重要ではない関数でもかまいません。 一方、JavaScript実装がこれらの関数を構文エラーとして扱う場合、関数が呼び出されなかったとしても、スクリプト全体が拒否されます。

開発者にとってこのような危険な関数の実装は望ましくありません。 ただし、インターネット上での存在は固定されているため、実質的に選択の余地はありません。

constはどうですか?


IEがconst宣言をサポートするかどうか疑問に思う人もいます。 constは、「名前付き定数」値を宣言する方法を提供する非標準のJavaScript拡張機能です。 典型的なアプリケーションは次のようになります。

const pi=3.14159;

いくつかのブラウザはこの機能をサポートしていますが、異常な状況の処理とエラーとして定義するものには大きな違いがあります。 constを「サポート」するブラウザの動作のいくつかの違いを示す例を次に示します。

  <code> //同じ名前の複数のconst宣言を持つ関数</ code> 


  <code>関数f(){</ code> 


  <code> alert( 'futing within f'); </ code> 


  <code> const x = 1;  //定数xを1として宣言します</ code> 


  <code> alert(x); </ code> 


  <code> const x = 2;  //定数xを2としてオーバーライド</ code> 


  <code> alert(x); </ code> 


  <code> x = 3;  // xに3を設定してみます</ code> 


  <code> </ code> <code> alert(x); </ code> 


  <code>} </ code> 


  <code> alert( 'fabout call');  f(); </ code> 


ブラウザに応じて、コードは次のことを行います。



実際、 const宣言の非常に単純なアプリケーションのみが、宣言をサポートするさまざまなブラウザーと互換性があります。 何らかのエラーを引き起こす可能性のある、より複雑なアプリケーションまたはシナリオの多くは、異なるブラウザー間で互換性がありません。

実際のJavaScript実装では、ごく少数の些細なユースケースしかサポートできません。 また、この実装は、実際のWebページで使用可能な非典型的な境界線のケースと誤ったスクリプトで何かを行う必要があります。 標準化された仕様は、主にそのような状況のために存在する可能性があります。 通常、単純な一般的なユースケースをどうするかは明らかです。 境界線の場合、これには互換性のある実装の存在を保証する標準の仕様が必要です。

TC39はconstをES5に組み込むことを真剣に検討しており、初期のES5プロジェクトに存在しています。 ただし、その定義と他の広告との相互作用には多くの問題がありました。 最終的に、TC39でconstの標準化が仕様の「次の」改訂を待つことで合意に達しました。これにより、これらの他の問題のいくつかが解決される可能性があります。 本質的に、TC39委員会は、欠陥のある機能の標準化は望ましくないと判断しました。 代わりに、彼はconst標準化を将来に合わせて延期することを決定しました。この場合、1つの高度な設計をすべてのブラウザーに統合できます。

IE9はconst何をしますか? これまでのところ、グループは彼を支持しないという決定を固守しています。 これは、すべてのブラウザで利用可能になったことがないため、コンセンサス機能ではありません。 標準の仕様はありませんが、既存のすべてのブラウザー実装の間には意味上の大きな違いがあります。 これに加えて、TC39は既存の代替案を標準化しないことを決定し、ECMAScriptの将来のエディションでこの問題を再検討する予定であることが知られています。

多くのウェブサイト開発者がこのような広告を使用できるようにしたいという願望は理解できます。 ただし、関数が存在する必要がある場合、関数の条件付き宣言のような別の状況を作りたくはありませんが、Webサイト開発者はブラウザーの互換性を気にする場合は使用しないほうがよいでしょう。 最終的に、インターネットの最善の長期的解決策は、インターネットを使用から排除し、標準化プロセスが進むのを待つことです。

意思決定への原則的アプローチ


これらは、IE9を作成するときにどのような決定を下す必要があるかを示す4つの具体的なJavaScriptの例です。 インターネット上の他の標準やコンセンサス機能でも同様の問題が多く発生します。 いずれの場合も、同様の分析が実行されます。 そして、規格は何と言っていますか? 本当に必要なウェブサイトの数は? これは共通のセマンティクスを持つコンセンサス関数ですか? 互換性のない機能オプションがいくつかありますか? 標準化委員会はこの問題に取り組んでいますか? テストスイートはありますか? 採用は標準化プロセスを促進または妨げますか? 最終的に、それは主観的な判断の問題であり、したがって、意思決定に対する原則的で一貫したアプローチを確保するためにあらゆる努力をすることが重要です。

PSあなたはすでにHTML5でHabrを推定しましたか?

Source: https://habr.com/ru/post/J105644/


All Articles