暙準のJavaScriptラむブラリに関する考察。 Core.js

1人の子䟛がすべおをJavaScriptで蚘述し、クラむアントずサヌバヌは、䟿利で読みやすいず蚀った。 その埌、圌はもちろんダヌキヌに連れお行かれたした。

-むンタヌネットから


なんで 興味深いこず-​​JavaScript。 最新のWebおよびフロント゚ンドの基盀には、代替手段がありたせん。



JavaScriptは、ずりわけ、ここで説明する暙準ラむブラリです。 暙準ラむブラリずは、プログラマヌ偎の䞍必芁なアクションがなく、プラットフォヌム固有のAPIを含たない、任意のプラットフォヌム䞊に存圚するモゞュヌル、コンストラクタヌ、メ゜ッドを意味したす。 JavaScriptではなく、それにコンパむルされた蚀語で蚘述した堎合でも、ほずんどの堎合、その暙準ラむブラリを凊理する必芁がありたす。



䞀般に、Vanilla JavaScript暙準ラむブラリは優れおいたす。 これは、珟行バヌゞョンのECMA-262蚀語仕様3からドラフト6に基づく暙準ラむブラリだけではありたせん。APIの䞀郚は、ECMA-402囜際化APIなどの個別の仕様に配眮されたす。 setTimeout



など、JavaScriptが想像しがたい機胜の倚くは、Web暙準に関連しおいたす。 コン゜ヌルはたったく暙準化されおいたせん。事実䞊の暙準に䟝存する必芁がありたす。



しかし、それはそれほど暙準的ではなく、どこでも異なりたす。 叀いIEには、 Array#forEach, Function#bind, Object.create



、およびコン゜ヌルがなくおも、90幎の暙準ES3ラむブラリがすぐに利甚できたす。たずえば、倚くの人がすでに将来を最倧限に掻甚しおいるNode.jsがありたすES6。



サヌバヌずブラりザの䞡方で、可胜な限り最新であり、必芁な機胜を実装しおいる、これたでのずころ暙準化されおいない、ナニバヌサルで真に暙準的なラむブラリが必芁です。 この蚘事はcore.jsラむブラリヌに関するもので、暙準的なJavaScriptラむブラリヌに関する私の考えを実装しおいたす。 さらに、この蚘事は、最新の暙準化された暙準JavaScriptラむブラリヌに関するチヌトシヌトであり、その展望に぀いおのメモでもありたす。



コンテンツ、たたは出力で埗られるもの





譊告したす。マルチブックず最初の章は非垞にありふれたものです。すべおを読みたいずいう欲求はありたせん-䞊蚘の目次、興味のあるセクションたでスクロヌルしおください。



アプロヌチ




JavaScriptでラむブラリを䜜成するには、暙準ず呌ばれる3぀の䞻なアプロヌチがありたす。



最初のものはポリフィヌルのみの䜿甚、暙準化された機胜のみです。 時間ずずもにAPIが壊れないずいう具䜓的な信念。 このようなラむブラリを䜿甚するには、その知識は必芁ありたせん。察応するAPI蚀語の知識のみが必芁です。 䞀般的に、ポリフィルは1぀の暙準たたはその䞀郚に限定されたす。 たずえば、 es5-shimたたはes6-shim 。 このため、デフォルトで必芁な機胜を提䟛するには、耇数のポリフィルを接続する必芁がありたす。 内郚コンポヌネントは盞互に耇補するこずが倚いため、このセットは数癟キロバむトに達するこずがよくありたす。 そしお、私が持ちたいすべおの機胜が暙準化されおいるわけではありたせん。 他のラむブラリず競合する可胜性は無芖できたすが、ラむブラリを䜜成するずきに䟝存関係ずしおそれらを䜿甚するこずはありたせん。



2぀目は、 独自の名前空間にあるナヌティリティのセットです 。 モゞュラヌシステムに゚クスポヌトするか、1぀のグロヌバルオブゞェクトを䜜成したす。 たずえば、 UndescoreたたはそのLoDashのフォヌク。 通垞、それは非垞にコンパクトですが、可胜性は䞀連の単玔なナヌティリティによっお制限されたす。 ネむティブオブゞェクトを拡匵せず、倉曎をロヌルバックするnoConflict



メ゜ッドがしばしば存圚するため、他のラむブラリずの競合の可胜性は最小限です。他のラむブラリの安党な䟝存関係ずしおここで説明した他のメ゜ッドよりも優れおいたす。



3぀目は、 暙準化された機胜だけでなく、ネむティブオブゞェクトの拡匵です 。 たずえば、独自のメ゜ッドをプロトタむプ配列に远加するず、通垞、関数に配列を枡すよりも䟿利です。 今、このカテゎリでは、 Sugarルヌルが、 やがお-MooToolsずPrototypeになりたす。 倚くの䟿利な機胜が远加されたすが、倚くの堎合、メ゜ッドは互いにほが完党に耇補されたす。 倚盞性はここで展開する必芁がありたす-しかし、倚盞性の堎合、そのようなラむブラリは通垞、配列のプロトタむプメ゜ッド、 Function#bind



、および他のいく぀かに制限され、ほずんどの暙準を無芖したす。 玛争に関しおは、ここではすべおが非垞に悪いです。 このようなラむブラリは、倚くの堎合、同じ名前で異なるシグネチャを持぀メ゜ッドを䜿甚しおネむティブオブゞェクトを拡匵したす。 競合を避けるために、最終アプリケヌションを開発するずきは、ポリファむルをカりントせずにネむティブオブゞェクトを展開する耇数のラむブラリを䜿甚しないでください。たた、ラむブラリを蚘述するずき、このような䟝存関係は䞀般に受け入れられたせん。



1぀の汎甚暙準ラむブラリの代わりに、䞍必芁なトラブルなしで垌望する機䌚を提䟛するために、 Undescore / LoDash / Sugar + es5-shim、es6-shim、es6-symbol、setImmediate.js / asap、Moment.jsから寄せ集めを匕き出す必芁がありたす/ Intl.js、コン゜ヌルダミヌ ...など。



これらのアプロヌチのそれぞれからベストを取りたしょう。 core.jsの抂念は次のずおりです。





通垞のビルドの堎合、 core.jsの操䜜は非垞に明癜です。



 console.log(Array.from(new Set([1, 2, 3, 2, 1]))); // => [1, 2, 3] console.log('*'.repeat(10)); // => '**********' Promise.resolve(32).then(console.log); // => 32 setImmediate(console.log, 42); // => 42
      
      





ネむティブオブゞェクトを拡匵しないアセンブリの堎合、機胜はグロヌバルcore



オブゞェクトたたはモゞュラヌシステムに゚クスポヌトされたす。 たずえば、 Promise



コンストラクタヌはcore.Promise



ずしお䜿甚でき、 Array.from



メ゜ッドはcore.Array.from



ずしおArray.from



。 ラむブラリの远加ではなく、既存のプロトタむプに远加するこずを目的ずしたメ゜ッドは、コンストラクタヌが静的になりたす。たずえば、 core.String.repeat



はString.prototype.repeat



メ゜ッドの静的バヌゞョンです。



 var log = core.console.log; log(core.Array.from(new core.Set([1, 2, 3, 2, 1]))); // => [1, 2, 3] log(core.String.repeat('*', 10)); // => '**********' core.Promise.resolve(32).then(log); // => 32 core.setImmediate(log, 42); // => 42
      
      





ポリフィルのみをそれぞれ含むアセンブリは、それらを远加するだけです。 実際、通垞のアセンブリを䜿甚した䟋では、ポリフィルのみが䜿甚されおいたす。



 Node.jsぞのむンストヌル



 npm i core-js
      
      





アセンブリの1぀を接続しお、以䞋から遞択できたす。



 //  : require('core-js'); //     : var core = require('core-js/library'); // ,   : require('core-js/shim');
      
      





ブラりザ甚のビルド 





これらのアセンブリのいずれにも満足できない堎合は、独自のアセンブリを䜜成できたす。 たずえば、ネむティブオブゞェクトを展開せずに、コン゜ヌルモゞュヌルず単玔な日付圢匏のみが必芁です。 これを行うには、Node.jsをむンストヌルしたす。その埌、アセンブリに必芁な䟝存関係を持぀grunt-cli、core-jsをむンストヌルし、アセンブルしたす。



 npm i -g grunt-cli npm i core-js cd node_modules/core-js && npm i grunt build:date,console,library --path=custom uglify
      
      





その結果、ファむルcustom.js



、 custom.min.js



重量4.8kbおよびcustom.min.map



を取埗したす。 library



フラグは、ネむティブオブゞェクトを展開せずにアセンブリを指したす。 ここで 、必芁な機胜が属するモゞュヌルを確認できたす 最埌の列。



パヌト1束葉杖


誰かが理解しおいない堎合、束葉杖は、蚘事の文脈では、ラむブラリで利甚可胜な暙準化された機胜の倚愛者を意味したす。 それでは、行きたしょう



ECMAScript 5




おそらく誰もがECMAScript 5が暙準ラむブラリに远加するものを知っおいたす。 ES5をサポヌトしおいないほずんどすべおのブラりザヌは消滅したした。 叀いIEを陀きたす。 これたで、顧客はIE8のサポヌトを、そしお最も深刻な堎合はIE6のサポヌトもしばしば芁求したす。 近い将来、状況が倉わるこずを願っおいたす。 最も人気のあるES5の芪友はこのes5-shimで 、いく぀かの機胜はSugar、MooTools、Prototypeにありたすが、䞀郚のみです。 これは目新しさからはほど遠いので、䞍必芁な詳现-簡単な説明ず、必芁に応じおいく぀かの実装機胜なしで行うこずができたす。 もちろん、コヌドがIE8-をサポヌトしお蚘述されおいる堎合、蚘述子を操䜜するこずに疑問の䜙地はないこずを芚えおおくこずが重芁です。



配列メ゜ッド



配列のプロトタむプメ゜ッドから始めたしょう。 これは誰にでもよく知られおいたす



配列indexOfは、指定された倀に等しい最初の芁玠のむンデックスを返したす。倀が芋぀からない堎合は-1



返したす。

配列lastIndexOfは前のものず䌌おいたすが、最埌の芁玠のむンデックスを返したす。

配列forEachは、配列の各芁玠に察しお関数を呌び出したす。

Arraymapは、指定された配列の各芁玠に察する関数呌び出しの結果を含む新しい配列を返したす。

配列フィルタは、チェック関数の条件を満たすこの配列のすべおの芁玠を含む新しい配列を返したす。

配列everyは、配列内のすべおの芁玠がチェック関数の条件を満たすかどうかを確認したす。

配列someは、チェック関数の条件を満たす配列の芁玠が少なくずも1぀あるかどうかを確認したす。

Arrayreduceは、関数を䜿甚しお巊から右に配列を畳み蟌みたす。

配列reduceRightは、関数を䜿甚しお配列を右から巊に畳み蟌みたす。



 [1, 2, 3, 2, 1].indexOf(2); // => 1 [1, 2, 3, 2, 1].lastIndexOf(2); // => 3 [1, 2, 3].forEach(function(val, key){ console.log(val); // => 1, 2, 3 console.log(key); // => 0, 1, 2 }); [1, 2, 3].map(function(it){ return it * it; }); // => [1, 4, 9] [1, 2, 3].filter(function(it){ return it % 2; }); // => [1, 3] function isNum(it){ return typeof it == 'number'; } [1, '2', 3].every(isNum); // => false [1, '2', 3].some(isNum); // => true function add(a, b){ return a + b; } [1, 2, 3].reduce(add); // => 6 [1, 2, 3].reduceRight(add, ''); // => '321'
      
      





これらのメ゜ッドは基本的に実装されおいたすが、1぀の機胜がありたす。 配列メ゜ッドはゞェネリックであり、配列だけでなく、配列に䌌たオブゞェクトのコンテキストで呌び出すこずができたす 。この詳现に぀いおは、 以䞋で説明したす 。 そのため、ES5仕様によるず、文字列は配列のようなオブゞェクトであり、文字列の文字はむンデックスによっお取埗できたす。たずえば、 'string'[2] // => 'r'



ですが、叀いIEではそうではありたせん。 これらのメ゜ッドが文字列のコンテキストで適甚される堎合、文字列を配列にキャストしたす。 同じ問題を解決するには、必芁に応じお、叀いIEのArray#slice



ずArray#join



を眮き換えたす。



 Array.prototype.map.call('123', function(it){ return it * it; }); // => [1, 4, 9] Array.prototype.slice.call('qwe', 1); // => ['w', 'e'] Array.prototype.join.call('qwe', '|'); // => 'q|w|e'
      
      





さお、叀代の真実を忘れないでください。for for-in



ルヌプで配列をバむパスしないfor-in



ください
。 これは遅いだけでなく、IE8-サポヌトが必芁な堎合、キヌが適切であるかどうかを確認するこずも匷制したす-そうでなければ、配列の芁玠だけでなく、そのプロトタむプのメ゜ッドもバむパスしたす:)



静的メ゜ッドArray.isArrayは同じカテゎリに属したす。 このメ゜ッドは、オブゞェクトがプロトタむプチェヌンではなく、内郚クラスによる配列であるかどうかをチェックしたす。 䟿利ですが、普遍的ではありたせん。 オブゞェクトの分類に぀いおは、蚘事の第2郚である自転車で詳现に説明したす 。



 Array.isArray([1, 2, 3]); // => true Array.isArray(Object.create(Array.prototype)); // => false
      
      





オブゞェクトAPI



ECMAScript 3に基づくすべおのECMAScript 5オブゞェクトAPIメ゜ッドの完党な゚ミュレヌションは䞍可胜であり、郚分的です-倚くの堎合に可胜です。 ES5は、次のカテゎリのメ゜ッドをオブゞェクトAPIに远加したす。プロトタむプの䜜成䜜成/受信、オブゞェクトキヌの取埗、蚘述子の䜿甚。



 Object.createメ゜ッドは、プロトタむプからオブゞェクトを䜜成したす。 null



を枡すこずにより、プロトタむプなしでオブゞェクトを䜜成できたすが、これはECMAScript 3に基づいお行うこずは䞍可胜です。 iframe



基づく激しいゎミを䜿甚する必芁がありたす。 これがなぜ第2郚で私たちに明らかにされるのでしょう オプションで、 Object.defineProperties



に䌌た蚘述子オブゞェクトを受け入れたす。



 function Parent(/*...*/){ /*...*/ } Parent.prototype = {constructor: Parent /*, ... */} function Child(/*...*/){ Parent.call(this /*, ...*/); // ... } //   ES3 (  inherit  extend'): function Tmp(){} Tmp.prototype = Parent.prototype; Child.prototype = new Tmp; Child.prototype.constructor = Child; //   ES5: Child.prototype = Object.create(Parent.prototype, {constructor: {value: Child}}); var dict = Object.create(null); dict.key = 42; console.log(dict instanceof Object); // => false console.log(dict.toString) // => undefined console.log(dict.key) // => 42
      
      





 Object.getPrototypeOfメ゜ッドは、オブゞェクトのプロトタむプを返したす。 ECMAScript 3では、オブゞェクトのプロトタむプを取埗する保蚌された方法はありたせん。 オブゞェクトにconstructor



プロパティが含たれる堎合、おそらくプロトタむプはconstructor.prototype



たす。 Object.create



で䜜成されたオブゞェクトの堎合、プロトタむプを含むシンボルを远加し、キヌを受け取ったずきにそれを無芖したす 。 ただし、「正しい」 constructor



プロパティを指定せずにプロトタむプがオヌバヌラむドされたコンストラクタむンスタンスでは、 Object.getPrototypeOf



は正しく機胜したせん。



 var parent = {foo: 'bar'} , child = Object.create(parent); console.log(Object.getPrototypeOf(child) === parent); // => true function F(){} console.log(Object.getPrototypeOf(new F) === F.prototype); // => true F.prototype = {constructor: F /*, ...*/}; console.log(Object.getPrototypeOf(new F) === F.prototype); // => true F.prototype = {}; console.log(Object.getPrototypeOf(new F) === F.prototype); //  IE8-   
      
      





 Object.keysメ゜ッドは、オブゞェクトの独自の列挙キヌの配列を返したす。 Object.getOwnPropertyNamesは、オブゞェクト自䜓のキヌの配列を返したす。 および非䞊堎。 Object.keys



を䜿甚するず、すべおがシンプルに思えたすObject.keys



for-in



を介しおオブゞェクトをObject.keys



し、プロパティが独自のものであるかどうかを確認したす。 IEの「列挙䞍可胜な」列挙プロパティのバグではない堎合。 そのため、このようなプロパティを個別に確認する必芁がありたす。 同様に、䜿甚可胜な非衚瀺プロパティのリストを远加チェックするず、 Object.getOwnPropertyNames



もObject.getOwnPropertyNames



たす。



 console.log(Object.keys({q: 1, w: 2, e: 3})); // => ['q', 'w', 'e'] console.log(Object.keys([1, 2, 3])); // => ['0', '1', '2'] console.log(Object.getOwnPropertyNames([1, 2, 3])); // => ['0', '1', '2', 'length']
      
      





蚘述子のすべおが悪いので、ECMAScript 3はそれらをサポヌトしおいたせん。 ゲッタヌ/セッタヌを蚭定する方法はありたせん。 Object#__define[GS]etter__



持っおいるが、 Object.defineProperty



欠萜しおいるObject.defineProperty



消滅したした。 叀いIEでは、 VBScriptを䜿甚しお倒錯化するこずで、getter / setterを䜿甚しおオブゞェクトを䜜成できたすが、これは別のトピックです。 enumerable: false



プロパティはありたすが、蚭定するこずはできたせんが、 ObjectpropertyIsEnumerableを䜿甚しおそのようなものかどうかを確認するこずができたす 。 IE8には蚘述子を操䜜するためのメ゜ッドがありたすが、そうでない堎合はより適切ですDOMオブゞェクトでのみ機胜したす。 したがっお、IE8-でできるこずはスタブだけです。 Object.definePropertyおよびObject.definePropertiesの蚘述子のvalue



によっおプロパティvalue



蚭定し、 Object.getOwnPropertyDescriptorでvalue



ずenumerable



を正盎に取埗しvalue



。



 Object.freeze, Object.preventExtensions, Object.seal



どうですか スタブを陀き、゚ミュレヌションが䞍可胜になるだけでなく、次のような芳点もありたす。

Object.freeze、Object.preventExtensions、Object.seal、with、eval

あなたはおそらく決しお必芁ずしないだろうクレむゞヌたわごず。 それから離れおください。

-フェリックス・ガむれンデルファヌ

そしお、私は圌女に完党に同意したす。



その他



ECMAScript 5は、 Functionbindを介しおコンテキストバむンディングず基本的な郚分アプリケヌション機胜を远加したした。 この方法は玠晎らしいですが、JavaScriptで郚分的なアプリケヌションずコンテキストバむンディングの可胜性を解き攟぀には、それだけでは十分ではありたせん。トピックは察応するセクションで詳しく説明されおいたす。



 var fn = console.log.bind(console, 42); fn(43); // => 42 43
      
      





 Date.nowメ゜ッドは、珟圚の時刻を数倀衚珟で返したす。結果は+new Date



ず同じです。



 Date.now(); // => 1400263401642
      
      





 Stringtrimメ゜ッドは、行の先頭ず末尟から空癜を削陀したす。



 '\n  \n'.trim(); // => ''
      
      





JSON



モゞュヌルに぀いおは、IE8でサポヌトされおおり、このラむブラリのフレヌムワヌク内では、実装する理由はありたせん。 あなたが絶察に先史時代のIEでそれを必芁ずするならば-誰も䟋えばこの芪友を䜿うこずを気にしたせん。



ECMAScript 6




ECMAScript 5仕様は、決しお受け入れられなかったECMAScript 4仕様の代わりに急いで曞かれおおり、前䞖玀に採甚されたECMAScript 3にはあたり拡匵されおいたせんでした。 新機胜の远加は凍結され、ECMAScript 7の提案にはすべおの䞻芁な倉曎が加えられ、ドラフト仕様ぞの最近の倉曎のほずんどはバグ修正です。 したがっお、暙準ラむブラリでは、䞻にES6に焊点を圓おたす。



珟圚の゚ンゞンでサポヌトされおいるこずは、 この衚にはっきりず衚れおいたす 。





最も人気のあるES6の芪友は、 paulmillrのes6 - shimです。



暙準のECMAScript 6ラむブラリの䞀郚、たずえばProxy



これは最もおいしい機胜の1぀です、ECMAScript 5を実装するこずはできたせん。さらにECMAScript 3を実装するこずはできたせんが、ほずんどは完党ではないにしおも、少なくずも郚分的に「䞍正」に実装できたす。



プリプロセッサECMAScript 6+に぀いお少し



構文に぀いおは、このラむブラリのフレヌムワヌク内では、サポヌトを远加できたせん。 ただし、ECMAScript 6+の構文をECMAScript 3たたは5に倉換するプリプロセッサがここで助けになりたす。それらの膚倧な数がありたす。数個の䞀般的なものだけを考えおみたしょう。



そのような叀くお匷力なプロゞェクト、 Google Traceurがありたす。 読み取り䞍胜なコヌドを生成し、かなり重いランタむムを䜿甚するため、䜿甚を拒吊したした。



別のプロゞェクトは私にずっおはるかに魅力的なようです-6to5 。このプロゞェクトは新鮮で、驚くほど速く開発されおいたす。読みやすいコヌドを生成し、ゞェネレヌタヌをコンパむルするために䜿甚するランタむムリゞェネレヌタヌを陀き、独自のランタむムを䜿甚したせん。しかし、代わりに、圌は積極的に暙準ES6ラむブラリを䜿甚したす-䟋えば、Symbol.iterator



。デフォルトはes6-shimおよびes6-symbolです。これらはラむブラリに簡単に眮き換えられるため、このプリプロセッサは理想的なペアになりたす。コヌドをECMAScript 5に倉換したすが、䞻に暙準ラむブラリに関するものです。のObject.defineProperties



ようなメ゜ッドスタブでは、ほずんどすべおが叀いIEでも機胜したす。



暙準ラむブラリのプリプロセッサずポリフィヌルを䜿甚しお、ECMAScript 6を最倧限に䜿い始めるこずができたす。おそらく、いく぀かのささいなこずを陀いお。6to5でES6をコンパむルする機胜を備え



た非垞にシンプルなサンドボックスず、接続されたcore.jsラむブラリをスケッチしたした。䟋には、リンクがありたす。ただし、このラむブラリはECMAScript 6構文に䞀切結び付けられおいないため、ほずんどの䟋ではECMAScript 5構文を䜿甚したす。






たあ、今では、ECMAScriptの6の新しいデザむナヌのための暙準ラむブラリに移動し、コンセプトは、別の章で説明したす蚘号、コレクション、むテレヌタずの玄束、残りはここで怜蚎しおいきたす。



 Object.assign



この方法は倚くの人に期埅されおいたした。Object.assign cornyは、゜ヌスオブゞェクトの独自の列挙プロパティをすべおタヌゲットオブゞェクトにコピヌしたす。䟋



 var foo = {q: 1, w: 2} , bar = {e: 3, r: 4} , baz = {t: 5, y: 6}; Object.assign(foo, bar, baz); // => foo = {q: 1, w: 2, e: 3, r: 4, t: 5, y: 6}
      
      





たたObject.mixin



、列挙䞍可胜なプロパティをコピヌし、蚘述子を考慮に入れ、キヌワヌドを介しお取埗した芪を再割り圓おするメ゜ッドを远加するこずも蚈画されおいたしたsuper



。しかし、圌らはその远加を延期するこずにしたした。その類䌌物は、ラむブラリの自転車郚分にありたす。



 Object.is



JavaScriptの比范挔算子は通垞、かなり奇劙に動䜜したす。==



キャストのような挔算子でさえ忘れおください===







 NaN === NaN // => false 0 === -0 // => true,   : 1/0 === 1/-0 // => false
      
      





この堎合のために、蚀語には内郚SameValue比范アルゎリズムがありたす。それのためにNaN



あるNaN



ず、+0



そしお-0



明瞭な。 ECMAScript 6では、それらを挔算子is



およびずしお匕き出したかっisnt



たのですが、蚀語の比范挔算子はすでに十分ではないこずを認識しおおり、埌方互換性のために、Object.isメ゜ッドずしお取り出されたした。䟋



 Object.is(NaN, NaN); // => true Object.is(0, -0); // => false Object.is(42, 42); // => true,  '===' Object.is(42, '42'); // => false,  '==='
      
      





たた、ES6以降では、別の比范アルゎリズムが積極的に䜿甚されたす-SameValueZero、それNaN



は等しくNaN



、前のものず-0



は異なり、等しい+0



です。圌らは、キヌの䞀意提䟛コレクションを経由コレクションに参加する芁玠チェックするずき、それが䜿甚され、をArray#includes



。



 Object.setPrototypeOf



ES6では、既存のオブゞェクトのプロトタむプをむンストヌルするメ゜ッドが衚瀺されたすObject.setPrototypeOf



。䟋



 function Parent(){} function Child(){} Object.setPrototypeOf(Child.prototype, Parent.prototype); new Child instanceof Child; // => true new Child instanceof Parent; // => true function fn(){} Object.setPrototypeOf(fn, []); typeof fn == 'function'; // => true fn instanceof Array; // => true var object = {}; Object.setPrototypeOf(object, null); object instanceof Object; // => false
      
      





蚀語のプロトタむプの方向、機䌚-少なくずも最初の䟋-シンプルで明癜なプロトタむプの継承がECMAScript 5にないこずを考えるず、このように䞀芋必芁なのは奇劙です。このメ゜ッドなしで既存のオブゞェクトのプロトタむプを倉曎する唯䞀の方法は非暙準のプロパティ__proto__



です。珟時点では、IE10-を陀く珟圚のすべおのブラりザヌで、珟圚の実装プロトタむプのゲッタヌ/セッタヌでサポヌトされおいたすObject



。



プリミティブで、䞍必芁なチェックやオブゞェクトの戻りObject.setPrototypeOf



がなければ、バヌゞョンはシンプルに芋えるでしょう-セッタヌ__proto__



を匕き出しお、それから機胜を䜜りたす



 var setPrototypeOf = Function.call.bind(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set);
      
      





ただし、別の問題がここに衚瀺されたす-v8の叀い、しかしどこか関連するバヌゞョンでは、セッタヌ__proto__



を関数ずしお䜿甚できたせん。実装Object.setPrototypeOf



の堎合、キヌで倀を蚭定するだけです__proto__



。



私たちは生きおいたす




たた、ECMAScript 6ずラむブラリは䜜業のロゞックを倉曎しおいObject#toString



たす。このトピックは深刻ですが、蚘事の埌半でに぀いお説明したす。



配列メ゜ッド



静的メ゜ッドArray.from



およびArray.of



-ゞェネリック、それらが以倖の関数のコンテキストで実行される堎合、それらはArray



そのむンスタンスを䜜成したす。これに぀いお詳しく知りたい堎合は、この蚘事で新しい配列メ゜ッドに぀いお詳しく説明しおいたす。



のECMAScript 6は、非垞に有甚な方法が远加されたす- Array.from



。これは、反埩可胜で配列のようなオブゞェクトぞの汎甚キャストです。ほずんどの堎合、Array.prototype.slice.call



開始䜍眮ず終了䜍眮を指定せずに眮き換えられたす。さらに、このメ゜ッドは、オプションのマップコヌルバックずその実行コンテキストを受け入れたす。マップ・コヌルバックなしで反埩可胜な転送の堎合、結果は、オペレヌタの䜿甚に類䌌しおいる広がり配列リテラルで- [...iterable]



。䟋



 Array.from(new Set([1, 2, 3, 2, 1])); // => [1, 2, 3] Array.from({0: 1, 1: 2, 2: 3, length: 3}); // => [1, 2, 3] Array.from('123', Number); // => [1, 2, 3] Array.from('123', function(it){ return it * it; }); // => [1, 4, 9]
      
      





前のものずは異なり、 Array.ofメ゜ッドは珟圚ほずんど実甚的ではありたせん。サブクラスには、たずArray



配列リテラルの類䌌物ずしお必芁です[]



。䟋



 Array.of(1); // => [1] Array.of(1, 2, 3); // => [1, 2, 3]
      
      





メ゜ッドアレむの怜玢およびアレむfindIndexは、コヌルバック呌び出しお怜玢配列を搭茉したした。䟋



 function isOdd(val){ return val % 2; } [4, 8, 15, 16, 23, 42].find(isOdd); // => 15 [4, 8, 15, 16, 23, 42].findIndex(isOdd); // => 2 [4, 8, 15, 16, 23, 42].find(isNaN); // => undefined [4, 8, 15, 16, 23, 42].findIndex(isNaN); // => -1
      
      





配列メ゜ッド配列fillは、枡された倀で配列を埋めたす。オプションの匕数-開始䜍眮ず終了䜍眮。䟋



 Array(5).map(function(){ return 42; }); // => [undefined × 5],   .map  ""   Array(5).fill(42); // => [42, 42, 42, 42, 42]
      
      





文字列メ゜ッド



ここではすべおが簡単です。 文字列には最近たで- String#contains



が含たれおいたしたが、叀い名前で利甚できる限りArray#includes



匕き寄せられたした、文字列内の郚分文字列をチェックしたす。文字列startsWithおよび文字列endsWithは、文字列が特定の郚分文字列で開始たたは終了するかどうかを確認したす。これら3぀のメ゜ッドは、远加の匕数-開始䜍眮を取りたす。䟋



 'foobarbaz'.includes('bar'); // => true 'foobarbaz'.includes('bar', 4); // => false 'foobarbaz'.startsWith('foo'); // => true 'foobarbaz'.startsWith('bar', 3); // => true 'foobarbaz'.endsWith('baz'); // => true 'foobarbaz'.endsWith('bar', 6); // => true
      
      





Stringrepeatメ゜ッドは、指定された回数だけ繰り返される文字列を返したす。䟋



 'string'.repeat(3); // => 'stringstringstring'
      
      





ラむブラリには、マルチバむト文字ず正盎な行反埩子のサポヌトを改善するための ECMAScript 6/7メ゜ッドがただ远加されおいたせん;配列反埩子が文字列に䜿甚されたす。今、圌らは私が単にそれらを必芁ずしないずいう理由だけではありたせん。近い将来それらを远加するのは良いこずです。



数字を扱う



ECMAScript 6は、膚倧な数の数孊関数ず定数を远加したす。説明ず䟋はなく、リンクのみNumber.EPSILON、Number.parseFloat、Number.parseInt、Number.isFinite、Number.isInteger、Number.isNaN、Number.MAX_SAFE_INTEGER、Number.MIN_SAFE_INTEGER、Number.isSafeInteger、Math.acosh、Math.asinh、Math.atanh、Math.cbrt、Math.clz32、Math.cosh、Math.expm1、Math.hypot、Math.imul、Math.log1p、Math.log10、Math.log2、Math.sign、Math.sinh、Math.tanh、Math.trunc。



 ECMAScriptの6蚘号




JavaScriptでは、オブゞェクトのプロパティを非衚瀺にするのはかなり悪いです。プラむベヌトデヌタはクロヌゞャに栌玍できたす。これにより、オブゞェクトのプロトタむプではなく、コンストラクタ内でそれらを操䜜するメ゜ッドを宣蚀する必芁がありたす。ECMAScriptの5以降では、あなたが宣蚀するこずができたすenumerable: false



非衚瀺オブゞェクトのリストからプロパティこずを財産for-in



ず䞊Object.keys



が、それは信頌性の高い隠ぺいを提䟛しおいたせんが、 -キヌは䞀意ではないが、それはあなたがあるため、䜿甚する必芁の名前の競合を有しおいおもよく、ピックアップしお簡単にするこずができObject.defineProperty



、オブゞェクト蚘述子をこれはかなり面倒です。



ECMAScript 6では、カプセル化を簡玠化するために、以前はNameず呌ばれおいた新しいデヌタ型Symbolが導入されおいたす。シンボルは、オブゞェクトの䞀意のキヌずしお䜿甚するためのものです。䟋



 var Person = (function(){ var NAME = Symbol('name'); function Person(name){ this[NAME] = name; } Person.prototype.getName = function(){ return this[NAME]; }; return Person; })(); var person = new Person(''); console.log(person.getName()); // => '' console.log(person['name']); // => undefined console.log(person[Symbol('name')]); // => undefined,   Symbol    for(var key in person)console.log(key); // =>  'getName',       console.log(typeof Symbol()); // => 'symbol'
      
      





シンボルは完党にプラむベヌトではありたせん-メ゜ッドObject.getOwnPropertySymbols



はオブゞェクト自䜓のシンボルを返したす。これにより、クロヌン䜜成などの䜎レベルの操䜜をデバッグできたす。#WeakMapに基づいお、真にプラむベヌトなデヌタのストレヌゞを実装できたす。私芋では、この問題に察するより成功した解決策は、完党にプラむベヌトなバヌゞョンのキャラクタヌを远加するこずです。



珟時点で、キャラクタヌはv38で利甚可胜です。Chrome38以前のバヌゞョン- 実隓的機胜のフラグ付きから、Firefoxのナむトリヌビルドで33から始たりたす。IEで間もなく玄束されたす。䞻芁な最新ブラりザ。



もちろん、ES5に基づいた本栌的なポリフィリックなキャラクタヌは䞍可胜ですが、基本的な機胜オブゞェクトの通過for-in



や戻り䞍可Object.keys



キヌに関係しない䞀意のキヌの䜜成は、たずえば次のように非垞に簡単に実装されたす。



 window.Symbol || (function(){ var id = 0; window.Symbol = function(description){ if(this instanceof Symbol)throw new TypeError('Symbol is not a constructor'); var symbol = Object.create(Symbol.prototype) , tag = 'Symbol(' + description + ')_' + (++id + Math.random()).toString(36); symbol.tag = tag; Object.defineProperty(Object.prototype, tag, { configurable: true, set: function(it){ Object.defineProperty(this, tag, { enumerable : false, configurable: true, writable : true, value : it }); } }); return symbol; } Symbol.prototype.toString = function(){ return this.tag; } })();
      
      





呌び出されるず、Symbol



たずえば"Symbol(description)_m.y9oth2pcqaypsyvi"



、䞀意のキヌ文字列を生成し、このキヌのObject.prototype



セッタヌを蚭定したす。「文字」がキャストされるキヌ文字列によっお倀を蚭定しようずするず、セッタヌはenumerable: false



プロパティを珟圚のオブゞェクトに蚭定したす。ただし、このような「シンボル」には膚倧な数のマむナスがありたす。ここに䞀郚を瀺したす。





決定が非垞に疑わしい堎合、ここで䜕をしおいたすかプロゞェクトに必芁な文字数が少なく、自分自身を含たないオブゞェクトでそれらを䜿甚する予定がない堎合Object.prototype



、この゜リュヌションは機胜したす。それ以倖の堎合は、ラむブラリにいく぀かのヘルパヌを远加したす。Symbol.pure



利甚できるネむティブな文字ならば、それは文字を返し、ない-でセッタヌを远加するこずなく、独自の文字列のキヌを返しObject.prototype



、そしおSymbol.set



、利甚可胜な堎合、ネむティブシンボルは-ちょうどオブゞェクトのキヌ倀に敷蚭なし-䜿甚しおの倀が蚭定されたす。この原始的な方法で、䞊蚘の問題の半分を取り陀きたす。呌び出しの代わりにデヌタヘルパヌを䜿甚しお䞊蚘で䜿甚した䟋は次のようになりたす。Object.defineProperty



enumerable: false



Symbol







 var Person = function(){ var NAME = Symbol.pure('name'); function Person(name){ Symbol.set(this, NAME, name); } Person.prototype.getName = function(){ return this[NAME]; }; return Person; }();
      
      





前述のずおり、メ゜ッドObject.getOwnPropertySymbols



は远加したせん。そしお、文字列ず文字の䞡方のすべおのキヌをバむパスするための、暙準化された、倚かれ少なかれ普遍的な方法が必芁です。 ECMAScriptの6は、远加のモゞュヌルReflect



最初の堎所では、 -プラグのセットのためにProxy



。゚ミュレヌトする胜力がないため、実際にはProxy



モゞュヌルReflect



は必芁ありたせん。ただし、Reflect.ownKeys



オブゞェクトのすべおのキヌを返すメ゜ッドがありたす-文字列ず文字の䞡方、぀たりObject.getOwnPropertyNames + Object.getOwnPropertySymbols



。このメ゜ッドを远加したす。䟋



 var O = {a: 1}; Object.defineProperty(O, 'b', {value: 2}); O[Symbol('c')] = 3; Reflect.ownKeys(O); // => ['a', 'b', Symbol(c)]
      
      





 ES6は、キャラクタヌのグロヌバルなケヌスのような怪しいものも远加したす。それを操䜜するためのいく぀かの方法がありたす -Symbol.forず Symbol.keyForです。Symbol.for



レゞスタで怜玢し、キヌ文字列で文字を返したすが、芋぀かりたせん-新しい文字を䜜成し、レゞスタに远加しお返したす。Symbol.keyFor



送信された文字がレゞスタ内で䞀臎する文字列を返したす。䟋



 var symbol = Symbol.for('key'); symbol === Symbol.for('key'); // true Symbol.keyFor(symbol); // 'key'
      
      





さらに、ラむブラリはシンボルSymbol.iterator



ずをSymbol.toStringTag



積極的に䜿甚したす。



 ECMAScriptの6コレクション




ECMAScript 6には、4぀の新しいタむプのコレクションがMap, Set, WeakMap



ありWeakSet



たすおよび。型付き配列もありたすが、今のずころは配列なしで実行できたす。





それで、これらのコレクションは䜕ですか



 Map -Key-Valueのコレクション。JavaScript゚ンティティはキヌずしお機胜できたす-プリミティブずオブゞェクトの䞡方。回避策がありたす。むテレヌタずメ゜ッド.forEach



があり、芁玠の数はプロパティを介しお利甚できたす.size



。䟋



 var a = [1]; var map = new Map([['a', 1], [42, 2]]); map.set(a, 3).set(true, 4); console.log(map.size); // => 4 console.log(map.has(a)); // => true console.log(map.has([1])); // => false console.log(map.get(a)); // => 3 map.forEach(function(val, key){ console.log(val); // => 1, 2, 3, 4 console.log(key); // => 'a', 42, [1], true }); map.delete(a); console.log(map.size); // => 3 console.log(map.get(a)); // => undefined console.log(Array.from(map)); // => [['a', 1], [42, 2], [true, 4]]
      
      





 Set-䞀意の倀のコレクション。ず同様にMap



、回避策がありたす。䟋



 var set = new Set(['a', 'b', 'a', 'c']); set.add('d').add('b').add('e'); console.log(set.size); // => 5 console.log(set.has('b')); // => true set.forEach(function(it){ console.log(it); // => 'a', 'b', 'c', 'd', 'e' }); set.delete('b'); console.log(set.size); // => 4 console.log(set.has('b')); // => false console.log(Array.from(set)); // => ['a', 'c', 'd', 'e']
      
      





 WeakMap-キヌず倀のコレクション。オブゞェクトのみがキヌずしお機胜したす。匱い接続を䜿甚したす-キヌオブゞェクトがガベヌゞコレクタヌによっお削陀されるず、コレクションのキヌず倀のペアも削陀されたす。回避する方法.forEach



はありたせん.size



。むテレヌタもメ゜ッドもプロパティもありたせん。これは、プラむベヌトデヌタを栌玍するもう1぀の方法であり、より「正盎」ですが、文字を䜿甚する堎合ず比べおリ゜ヌスを集䞭的に䜿甚したす。将来、抜象参照が JavaScriptに远加される堎合、このようなプラむベヌトフィヌルドに䟿利な構文が衚瀺されたす。䟋



 var a = [1] , b = [2] , c = [3]; var wmap = new WeakMap([[a, 1], [b, 2]]); wmap.set(c, 3).set(b, 4); console.log(wmap.has(a)); // => true console.log(wmap.has([1])); // => false console.log(wmap.get(a)); // => 1 wmap.delete(a); console.log(wmap.get(a)); // => undefined //      var Person = (function(){ var names = new WeakMap; function Person(name){ names.set(this, name); } Person.prototype.getName = function(){ return names.get(this); }; return Person; })(); var person = new Person(''); console.log(person.getName()); // => '' for(var key in person)console.log(key); // =>  'getName'
      
      





 WeakSet-さお、ポむントを埗る。比范的最近ドラフト仕様に登堎したため、ブラりザのサポヌトはかなり匱いです。䟋



 var a = [1] , b = [2] , c = [3]; var wset = new WeakSet([a, b, a]); wset.add(c).add(b).add(c); console.log(wset.has(b)); // => true console.log(wset.has([2])); // => false wset.delete(b); console.log(wset.has(b)); // => false
      
      





これらのコレクションはすべお、準線圢怜玢時間を提䟛する必芁がありたす。キヌの䞀意性は、SameValueZero比范アルゎリズムによっお提䟛されたす。



最新のjs゚ンゞンに察するこれらのコレクションのサポヌトは䜕ですかずおも良い。





ほずんどすべおの珟圚の実装収集方法.add



ず.set



返さないthis



-これらのメ゜ッドは動䜜したせん収集チェヌンを埋めるために。しかし、それは簡単に扱われたす。



コレクションをむテレヌタで初期化するには、コンストラクタヌのラッパヌでも十分です。これにより、コレクションが䜜成され、芁玠が远加されたす。むテレヌタに぀いおは、次の章で説明したす。



さお、コレクション自䜓の倚盞性をさらに怜蚎しおください。これらのコレクションの本栌的な実装-高速でありながらクリヌンで、ECMAScript 5に基づくメモリリヌクWeakMap甚はありたせんが、劥圓な劥協案を芋぀けるこずができたす。



マップずセットの実装



ほずんどのポリフィルは実装を衚したすMap



かむンスタンスMap



-2぀の配列、キヌず倀。芁玠を受け取るず、キヌの配列で䞀臎するものを探し、結果のむンデックスの倀の配列から芁玠を返したす。たたは、削陀を最適化するための代替手段は、゚ントリオブゞェクトのチェヌンです。䞡方の堎合に䜕が問題になっおいたすかこれは非垞に遅く、芁玠を芋぀ける難しさはOn、uniq操䜜の耇雑さはOn 2です。これはどのように私たちを脅かしたすか ここに小さなテストがありたす



 var array = []; for(var i = 0; i < 100000; i++)array.push([{}, {}]); array = array.concat(array); console.time('Map test'); var map = new Map(array); console.timeEnd('Map test'); console.log('Map size: ' + map.size);
      
      





200,000のオブゞェクトのペア将来のKey-Valueの配列を䜜成したす。そのうち100,000は䞀意であり、この配列からコレクションを䜜成したすMap



。たずえば、Firefoxで



ネむティブのものをテストしたしょうMap



。



 Map test:   Map test: 46.25 Map size: 100000
      
      





そしお今Map



、最も人気のある ECMAScript 6の愛奜家のものです。



 Map test:   Map test: 506823.31 Map size: 100000
      
      





箄8.5分。新しい芁玠をそれぞれ远加しようずするず、既に远加されおいる100,000個たで䞊べ替える必芁がありたす。このこずから、このアプロヌチは非垞に小さなコレクションにのみ適しおいるず結論付けるこずができたす。



ハッシュテヌブルを䜿甚しお、サブリニアポリフィルの速床を実珟できたす。 ECMAScript 5では、Object



文字列のみをキヌずしお䜿甚しおいたす。䞊蚘でテストしたポリファむルには、小さな最適化がありたす-コレクションアむテムを芋぀ける平均的な耇雑さをO1に枛らす単玔な関数によるキヌ文字列たたは数字の怜玢むンデックス



 function fastKey(key){ if(typeof key === 'string')return '$' + key; else if(typeof key === 'number')return key; return null; };
      
      





同様に、他のプリミティブぞのクむックアクセスを実装できたす。しかし、Map



プリミティブずしおのみ効果的に䜿甚できるキヌずしお、なぜ必芁なのでしょうかこれに察凊Object.create(null)



したす。オブゞェクトキヌの䞀意の識別子文字列を取埗および取埗するこずは䞍可胜です。したがっお、ルヌルをわずかに砎る必芁がありたす。必芁に応じお、オブゞェクトにキヌを蚭定するための識別子を持぀シンボルを远加したしょう。このようなもの







 var STOREID = Symbol('storeId') , id = 0; function fastKey(it){ //    'S'      'P'    if(it !== Object(it))return (typeof it == 'string' ? 'S' : 'P') + it; //      -  if(!Object.hasOwnProperty.call(it, STOREID))it[STOREID] = ++id; //     'O' return 'O' + it[STOREID]; }
      
      





Map



2぀の配列たたは芁玠オブゞェクトのチェヌンでObject



はなく、キヌず倀の2぀のハッシュに実装したす。远加の順序でコレクションをトラバヌスするために別のキヌ/倀ストアは必芁ありたせんすべおの゚ンゞンでは、オブゞェクトキヌは数字キヌを陀き、远加の順序で栌玍されたすが、ここではすべおのキヌにプレフィックス文字があるため、存圚したせん。合蚈



 Map test:   Map test: 669.93 Map size: 100000
      
      





もちろん、ネむティブのものよりも遅いですが、うたくいくず思いたす。はい、キヌオブゞェクトに隠しプロパティを蚘述したす-キヌずしおfrozen-objectsを䜿甚するこずはできたせんが、蚱容可胜な速床が埗られたす。Set



1ハッシュで同様に実装されたす。



疎結合コレクションの実装



匱結合コレクションの実装はさらに簡単です。むテレヌタ、メ゜ッド.forEach



、プロパティはありたせん.size



。コレクションオブゞェクトにキヌず倀を保存する堎合、それはもはや疎結合ではなくなりたす-キヌ/倀は削陀されず、Set



andの削陀されたバヌゞョンを取埗しMap



たす。倚かれ少なかれ合理的な解決策は長い間知られおいたす-キヌに倀を保存し、その識別子のみをコレクションオブゞェクトに保存するこずです。倀はキヌに保存されるため、保存されたデヌタのプラむバシヌはポリファむルで倱われたす。



倧幅に簡玠化された実装は次のようになりたす。
 window.WeakMap || (function(){ var id = 0 , has = Function.call.bind(Object.prototype.hasOwnProperty) , WEAKDATA = Symbol('WeakData') , ID = Symbol('ID'); window.WeakMap = function(){ if(!(this instanceof WeakMap))throw TypeError(); this[ID] = id++; } Object.assign(WeakMap.prototype, { 'delete': function(key){ return this.has(key) && delete key[WEAKDATA][this[ID]]; }, has: function(key){ return key === Object(key) && has(key, WEAKDATA) && has(key[WEAKDATA], this[ID]); }, get: function(key){ if(key === Object(key) && has(key, WEAKDATA))return key[WEAKDATA][this[ID]]; }, set: function(key, value){ if(key !== Object(key))throw TypeError(); if(!has(key, WEAKDATA))key[WEAKDATA] = {}; key[WEAKDATA][this[ID]] = value; return this; } }); })();
      
      





キヌ参照を削陀するずき、それがコレクションに残っおいないこず、そしおそれに応じおメモリがリヌクしないこずを確認したしょう



 // <-   snapshot 1 var array = []; for(var i = 0; i < 100000; i++)array[i] = {}; var wm = new WeakMap(); for(var i = 0; i < 100000; i++)wm.set(array[i], {}); // <-   snapshot 2 array = null; // <-   snapshot 3
      
      









ただし、堎合によっおは、メモリリヌクの問題が残るこずがありたす。コレクションオブゞェクトが削陀された埌、倀はキヌに関連付けられたたたになり、キヌであったオブゞェクトが削陀されるたでメモリリヌクが発生したす。そのため、コレクションWeakMap



がキヌよりも長生きするようにシステムを蚭蚈する䟡倀がありたす。誰かがメモリリヌクの問題を回避しようずしおいたすが、これは難解性のカテゎリ- たったく同じケヌスでのメモリリヌクです。この問題は



実装WeakSet



に残りたすが、最小化されたす-重いオブゞェクトになる可胜性のある倀の代わりに、コレクション内の存圚フラグのみがキヌに保存されたす。



 ECMAScriptの6むテレヌション




ECMAScript 6は、むテレヌタプロトコルを導入したす。これは、コレクションを暪断するための普遍的な方法などです。構文的な構造もそれに適甚されるため、それらに぀いおも考慮したしょう。しかし、たず第䞀に、これは暙準ラむブラリたたは構文の䞀郚ではなく、抂念です。むテレヌタプロトコルには以䞋を含めるこずができたす。





構文はこれの䞀郚であるため、この章では$for



、これらの構文構成の機胜の䞀郚を実装するモゞュヌルも怜蚎したす。ラむブラリをES6 +プリプロセッサで䜿甚する堎合は、このモゞュヌルなしで安党にビルドできたす。



 むテレヌタは、.next



フィヌルドを持぀オブゞェクトを返すメ゜ッドを持぀オブゞェクトです.done



-むテレヌタのトラバヌスが完了し、.value



珟圚のステップの倀です。䟋は、正の数の反埩子を䜜成するメ゜ッドです。これにより、0から指定された敎数 sandboxたでのすべおの敎数をバむパスできたす。



 function NumberIterator(number){ var i = 0; return { next: function(){ return i < number ? {done: false, value: i++} : {done: true}; } } } var iter = NumberIterator(3); iter.next(); // => {done: false, value: 0} iter.next(); // => {done: false, value: 1} iter.next(); // => {done: false, value: 2} iter.next(); // => {done: true}
      
      





 反埩可胜オブゞェクト反埩可胜-Symbol.iterator



反埩子を返すメ゜ッドをキヌに含むオブゞェクト。したがっお、反埩子を反埩可胜にSymbol.iterator



するには、を返すキヌによるメ゜ッドが必芁this



です。たずえば、数字を反埩可胜にしたす sandbox



 Number.prototype[Symbol.iterator] = function(){ return NumberIterator(this); } Array.from(10); // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
      
      





に泚意しおくださいSymbol.iterator



。 Firefoxはむテレヌタプロトコルをサポヌトしおいたすが、安定したビルドでは文字はただなく、代わりにSymbol.iterator



文字列が䜿甚されたす"@@iterator"



。シンボルは、ナむトリヌビルド、およびでさえ登堎したしたSymbol.iterator



が、文字列はむテレヌタプロトコルで匕き続き䜿甚されたす"@@iterator"



。 Firefoxのむテレヌタプロトコルを壊さないために、ラむブラリ内で、キヌSymbol.iterator



存圚しない堎合は䜜成ずキヌの䞡方でむテレヌタを取埗するメ゜ッドを耇補したす"@@iterator"



。 v8では、Chrome 38にむテレヌタプロトコルが完党にサポヌトされたした。



 Generator-䞀時停止できる機胜。拡匵むテレヌタむンタヌフェむスを持぀オブゞェクトを返したす。構文に぀いおは詳しく説明したせん。たずえば、この蚘事を参照しおください。プリプロセッサの堎合、おそらく最悪の郚分はECMAScript 6です。ゞェネレヌタを䜿甚する堎合の反埩可胜な数倀の䟋は、非垞に単玔に芋えたす sandbox。



 Number.prototype[Symbol.iterator] = function*(){ for(var i = 0; i < this;)yield i++; } Array.from(10); // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
      
      





 ルヌプはfor-of



反埩可胜なオブゞェクトをバむパスするように蚭蚈されおいたす。反埩可胜な数倀を䜿甚した䟋では、次のように機胜したす sandbox



 for(var num of 5)console.log(num); // => 0, 1, 2, 3, 4
      
      





でのECMAScript 6 iskaropkiを繰り返すString, Array, Map, Set



ずArguments



。さらに、Array, Map



これらにSet



はメ゜ッドが.keys, .values



あり.entries



、それぞれキヌ、倀、およびキヌず倀のペアの反埩子を返したす。Core.jsは、デヌタむテレヌタずメ゜ッドを远加したす。ルヌプずずもに、for-of



次のようになりたす sandbox



 var string = 'abc'; for(var val of string)console.log(val); // => 'a', 'b', 'c' var array = ['a', 'b', 'c']; for(var val of array)console.log(val); // => 'a', 'b', 'c'.    - .values for(var val of array.values())console.log(val); // => 'a', 'b', 'c' for(var key of array.keys())console.log(key); // => 0, 1, 2 for(var [key, val] of array.entries()){ console.log(key); // => 0, 1, 2 console.log(val); // => 'a', 'b', 'c' } var map = new Map([['a', 1], ['b', 2], ['c', 3]]); for(var [key, val] of map){ //    - .entries console.log(key); // => 'a', 'b', 'c' console.log(val); // => 1, 2, 3 } for(var val of map.values())console.log(val); // => 1, 2, 3 for(var key of map.keys())console.log(key); // => 'a', 'b', 'c' for(var [key, val] of map.entries()){ console.log(key); // => 'a', 'b', 'c' console.log(val); // => 1, 2, 3 } var set = new Set([1, 2, 3, 2, 1]); for(var val of set)console.log(val); // => 1, 2, 3.    - .values for(var val of set.values())console.log(val); // => 1, 2, 3 for(var key of set.keys())console.log(key); // => 1, 2, 3.  .keys  .values for(var [key, val] of set.entries()){ //  Set   .entries     console.log(key); // => 1, 2, 3 console.log(val); // => 1, 2, 3 } var list = (function(){return arguments})(1, 2, 3); for(var val of list)console.log(val); // => 1, 2, 3
      
      







このサむクルの構文サポヌトではすべおが非垞に悪いので、ES6 +プリプロセッサを䜿甚しない人のために、同様の機胜for-of



 sandboxを実装するヘルパヌをラむブラリに远加したす。



 $for(new Set([1, 2, 3, 2, 1])).of(function(it){ console.log(it); // => 1, 2, 3 }); // 2  $for -  entries -    2  $for([1, 2, 3].entries(), true).of(function(key, value){ console.log(key); // => 0, 1, 2 console.log(value); // => 1, 2, 3 }); // 2  .of -    $for('abc').of(console.log, console); // => 'a', 'b', 'c' //    ,    false $for([1, 2, 3, 4, 5]).of(function(it){ console.log(it); // => 1, 2, 3 if(it == 3)return false; });
      
      





オブゞェクトのプロトタむプarguments



は-Object.prototype



ですから、むテレヌタをプロトタむプに入れるメ゜ッドを眮くこずはできたせん。ネむティブオブゞェクトを拡匵せずに、 core.jsをラむブラリずしおビルドするオプションもありたす。これらの理由から、我々は、オブゞェクトが反埩可胜であるかどうかをテストするには、ヘルパヌのカップルを実行し、むテレヌタオブゞェクトを取埗する-$for.isIterable(foo)



アナログずしおSymbol.iterator in foo



および$for.getIterator(foo)



アナログずしおfoo[Symbol.iterator]()







 var list = (function(){return arguments})(1, 2, 3); console.log($for.isIterable(list)); // => true console.log($for.isIterable({})); // => false var iter = $for.getIterator(list); console.log(iter.next()); // => {value: 1, done: false} console.log(iter.next()); // => {value: 2, done: false} console.log(iter.next()); // => {value: 3, done: false} console.log(iter.next()); // => {value: undefined, done: true}
      
      





でのECMAScript 6぀のむテレヌタを初期化するために䜿甚されおいるコレクション Map, Set, WeakMap, WeakSet



、配列、埌にをArray.from



自分の予想方法Promise.all, Promise.race



で仕事に玄束。



関数、コンストラクタヌ、および配列リテラルを呌び出すずきに適甚されるスプレッド挔算子も、反埩可胜なオブゞェクトを必芁ずしたすが、これは暙準ラむブラリからはほど遠いトピックです。今すぐ䜿甚したいずいう芁望がありたす-歯の䞭のプリプロセッサ。䟋



 [...new Set([1, 2, 3, 2, 1])]; // => [1, 2, 3] console.log(1, ...[2, 3, 4]); // => 1, 2, 3, 4 var map = new Map([[1, 'a'], [2, 'b']]); new Array(...map.keys(), 3); // => [1, 2, 3]
      
      





他のすべおの堎合、配列/ゞェネレヌタヌ内包衚蚘配列/ゞェネレヌタヌの抜象化むテレヌタヌプロトコルにも属したす。以前はECMAScript 6ドラフトに含たれおいたしたが、 Firefoxでは長い間サポヌトされおいたしたが、ECMAScript 7たで延期されたした。これは、フィルタヌ凊理ず倉換を䜿甚しお、反埩可胜なオブゞェクトから配列たたはむテレヌタヌを生成する機胜です。぀たり 構文filter



およびmap



任意のiteriruemuhオブゞェクトに぀いお
。最埌の配列の砎壊はサポヌトされおいたせんが、FFで動䜜する䟋を陀きたす。すべおが6to5ずTraceurで機胜したす。䟋



 var ar1 = [for(i of [1, 2, 3])i * i]; // => [1, 4, 9] var set = new Set([1, 2, 3, 2, 1]); var ar2 = [for(i of set)if(i % 2)i * i]; // => [1, 9] var iter = (for(i of set)if(i % 2)i * i); iter.next(); // => {value: 1, done: false} iter.next(); // => {value: 9, done: false} iter.next(); // => {value: undefined, done: true} var map1 = new Map([['a', 1], ['b', 2], ['c', 3]]); var map2 = new Map((for([k, v] of map1)if(v % 2)[k + k, v * v])); // => Map {aa: 1, cc: 9}
      
      





私に関しおは-玠晎らしいこずです。それも単なる構文です。



 ES6プリプロセッサを䜿甚する予定がない人のために、モゞュヌルの䞀郚ずしお、同様の絶察的な自転車を远加したす$for



。呌び出しが$for



むテレヌタ高床な方法を返しof



た䞊、filter, map



およびarray



。メ゜ッドfilter



ずはmap



、むテレヌタを返したす。これにより、前のむテレヌタの倀をフィルタリングたたは倉換したす。この反埩子は、反埩子ず同じメ゜ッドによっお拡匵されたす$for



。このメ゜ッドarray



は、珟圚のむテレヌタを配列に倉換し、オプションのマップコヌルバックを受け入れたす。これらすべおのメ゜ッドには、2番目のオプションの匕数、実行コンテキストがありたす。$for



フラグを受け入れる堎合entries



、チェヌン内のすべおのコヌルバックは、匕数のペアで起動されたす。



䟋



 var ar1 = $for([1, 2, 3]).array(function(v){ return v * v; }); // => [1, 4, 9] var set = new Set([1, 2, 3, 2, 1]); var ar1 = $for(set).filter(function(v){ return v % 2; }).array(function(v){ return v * v; }); // => [1, 9] var iter = $for(set).filter(function(v){ return v % 2; }).map(function(v){ return v * v; }); iter.next(); // => {value: 1, done: false} iter.next(); // => {value: 9, done: false} iter.next(); // => {value: undefined, done: true} var map1 = new Map([['a', 1], ['b', 2], ['c', 3]]); var map2 = new Map($for(map1, true).filter(function(k, v){ return v % 2; }).map(function(k, v){ return [k + k, v * v]; })); // => Map {aa: 1, cc: 9}
      
      





リテラルでは、ES5の関数はやや扱いにくいですが、矢印関数では、構文理解を䜿甚するのずほが同じになりたす。



反埩子に察する他の操䜜をモゞュヌル$for



に远加するこずができたす。これにより、反埩可胜なオブゞェクトをトラバヌスおよび倉換する普遍的で怠zyな反埩子プロトコルなど方法が提䟛されたす。しかし、将来のために延期したす。たたは倚分地獄に。



ラむブラリはさらに2぀のむテレヌタtimes、twoを远加したす。Dict



コンストラクタは反埩可胜なオブゞェクトを期埅したすが、むテレヌタに関連付けられたすべおのバむクをこの章にドラッグしたせん。



 ECMAScriptの6玄束




非同期性ずJavaScriptは、倚くの人にずっおほが同矩語です。これはECMAScript 5暙準の非同期性にすぎず、たったく䜕もありたせん。などであっおも、このような基本的な技術setTimeout



ずsetInterval



W3CずWHATWGのりェブ基準が蚭けられおおり、それらに぀いお話もう少し。最初のクラスのオブゞェクトずしお機胜しない限り、コヌルバックの転送は䟿利です。これにより、コヌルバックhellが発生したす。非同期関数の䞊列および順次実行を簡玠化する1぀の方法は、async.jsなどのラむブラリを䜿甚するこずです。



非同期プログラミングを簡玠化する別のアプロヌチは、Promiseテンプレヌトです。非同期関数が返すこずができるpromiseオブゞェクトを䜿甚しお、その結果をサブスクラむブできたす。結果をサブスクラむブできるメ゜ッドは、新しいプロミスを返したす。これは、プロミスをチェヌンに配眮するこずにより、コヌドをより適切に構成するのに圹立ちたす。たた、Promiseぱラヌ凊理の問題を解決したす。非同期コヌドでtry-catch



は機胜せず、コヌルバック匕数で゚ラヌを枡す必芁があり、コヌドがさらに混乱する堎合がありたす。 promiseチェヌンの最埌に、メ゜ッドreject



ずthrowの䞡方でスロヌされるミスが発生する可胜性がありたすthrow



。QやRSVPの



ようなPromiseラむブラリが䞀般的です。時間が経぀に぀れお、暙準が登堎したしたPromises / A +。すべおのプロミスは非同期に解決され、メ゜ッドを䜿甚しお結果をサブスクラむブできたす.then



最初の匕数は正垞終了時に実行される関数、2番目ぱラヌが発生した堎合。



そのため、非同期コヌドでの䜜業を最終的に暙準化するために、ECMAScript 6 はPromises / A +暙準ず互換性があり、ほずんどの機胜を最小限に抑えながら、promise実装を远加したした。それらに぀いおは特に説明したせん。詳现に぀いおはこちら翻蚳ですが、少し時代遅れです、こちらたたはこちらをご芧ください。 ES6 Promiseはv8ずFirefoxですでに利甚可胜です。ポリファむルがありたす-es6-promiseずnative-promise-only。



のECMAScript 6の玄束の実斜は、コンストラクタでPromise



2コヌルバックを枡される関数を、受け入れる-最初は、第二に障害が発生した玄束を、こずができたす。さらにthen



、ES6 promiseにはメ゜ッドが含たれおいたす。これは、最初の匕数をcatch



省略した堎合の省略圢でありthen



、それを䜿甚するず゚ラヌをサブスクラむブできたす。䟋



 var log = console.log.bind(console); function sleepRandom(time){ return new Promise(function(resolve, reject){ // resolve   , reject -   //      setTimeout(resolve, time * 1e3, 0 | Math.random() * 1e3); }); } log(''); // =>  sleepRandom(5).then(function(result){ log(result); // => 869,  5 . return sleepRandom(10); }).then(function(result){ log(result); // => 202,  10 . }).then(function(){ log('  '); // =>    throw Error('!'); }).then(function(){ log('   - '); }).catch(log); // => Error: '!'
      
      





私は玄束゚ンゞンを暙準に完党に適応させるのが面倒だったので、core.jsの promise カヌネルはネむティブの玄束のみのラむブラリに基づいおおり、そこからコヌドはほずんど残っおいたせん。非同期性を確保するためにprocess.nextTick



、倚盞性setImmediateのメ゜ッドも䜿甚されたす。



ヘルパヌのペアは、それぞれ、正垞に完了した、たたは枡された倀で゚ラヌが発生したプロミスPromise.resolve



をPromise.reject



返したす。圌Promise.resolve



が玄束を受け入れた堎合、圌はそれを返したす。たた、他のthenableたずえば、jQuery Deferredをpromiseに倉換するために䜿甚するこずもできたす。暙準の叀いバヌゞョンでは、このための別のメ゜ッドがありたした-Promise.cast



。䟋



 Promise.resolve(42).then(log); // => 42 Promise.reject(42).catch(log); // => 42 Promise.resolve($.getJSON('/data.json')); // => ES6 promise
      
      





ヘルパヌPromise.all



は、枡された反埩可胜なコレクションのすべおのプロミスが解決されたずきに解決されるプロミスを返したすv8では、配列でのみ機胜するようになりたした。ラむブラリ内でただ修正を開始しおいたせん。他の䜕かで䜿甚する意味はありたせん。玄束ではないコレクションの芁玠は、を通しお玄束に導かれPromise.resolve



たす。䟋



 Promise.all([ 'foo', sleepRandom(5), sleepRandom(15), sleepRandom(10) //  15   -  ]).then(log); // => ['foo', 956, 85, 382]
      
      





ヘルパヌPromise.race



は前のものず䌌おいたすが、枡されたコレクションから少なくずも1぀のプロミスが解決されるず解決されるプロミスを返したす。私の謙虚な意芋では、ずは異なりPromise.all



、完党には少し違いたすが、それは無意味です。その助けがなければ、玄束が解決される時間を制限するのが少し簡単になりたす。䟋



 function timeLimit(promise, time){ return Promise.race([promise, new Promise(function(resolve, reject){ setTimeout(reject, time * 1e3, Error('Await > ' + time + ' sec')); })]); } timeLimit(sleepRandom(5), 10).then(log); // =>  5    853 timeLimit(sleepRandom(15), 10).catch(log); // Error: Await > 10 sec
      
      





 ECMAScriptの7で提案されおいる加えおいるためであっおも玄束しお、非同期JavaScriptは、利䟿性の面で改善の䜙地があり、非同期関数構文のキヌワヌドを拡匵async / await



に基づいおおり、発電機、発電機ず玄束リタヌンの玄束:)この構文は、すでにサポヌトされおいるこず Traceur、および 6to5。䟋



 var delay = time => new Promise(resolve => setTimeout(resolve, time)); async function sleepRandom(time){ await delay(time * 1e3); return 0 | Math.random() * 1e3; } async function sleepError(time, msg){ await delay(time * 1e3); throw Error(msg); } (async () => { try { log(''); // =>  log(await sleepRandom(5)); // => 936,  5 . var [a, b, c] = await Promise.all([ sleepRandom(5), sleepRandom(15), sleepRandom(10) ]); log(a, b, c); // => 210 445 71,  15 . await sleepError(5, '!'); log('  '); } catch(e){ log(e); // => Error: '!',  5 . } })();
      
      





やがお、Promiseは暙準の非同期JavaScript APIの倚くを倉曎したす。グロヌバル関数は既に暙準化されおいたすpolyphilfetch



- XMLHttpRequest



それを玄束するシンプルで䟿利なラッパヌ。オファヌは、远加する、ず私はシンプルを远加するず思いたすが、倚くの堎合、必芁に応じお、機胜delay



前の䟋の機胜ず同様に、指定した時間埌に解決されるの玄束を返す-さよならをsetTimeout



。おそらくdelay



、このラむブラリに远加するずいいでしょう。



 MozillaのJavaScriptの配列のメ゜ッドの静的バヌゞョン




䞊蚘のむテレヌタプロトコルを調べたした。これは、JavaScriptでコレクションをクロヌルするための唯䞀の暙準ではありたせん。よりシンプルで、より速く、より叀いものがありたす。これらは配列のようなオブゞェクトです。



JavaScriptには配列に加えお、JavaScriptに類䌌した倚くの゚ンティティがありたすが、同時に配列はありたせん。配列のようなこれらのオブゞェクトには、スキップ可胜.length



なキヌ0〜.length



による長さず芁玠が含たれおいたす。「穎」が発生したす。それらはArray.prototype



それぞれ含たれおおらず、それぞれ配列メ゜ッドもありたせん。これは、オブゞェクトarguments



、文字列正匏にはIE8 +、型付き配列配列、ただしそれ自䜓は含たれたせんArray.prototype



、DOM芁玠のコレクション、jQueryオブゞェクトなどです。



ほがすべおの配列プロトタむプメ゜ッドはゞェネリックです仕様倉換レポヌトずしお-「意図的に汎甚」機胜。起動されたコンテキストのオブゞェクトが配列である必芁はありたせん。たぶん.concat



そうではない。
倚くの人がそのようなデザむンに粟通しおいるず思いたす



 Array.prototype.slice.call(arguments, 1); //  [].slice.call(arguments, 1);
      
      





面倒で䞍明瞭。



ECMAScript 6はArray.from



メ゜ッドを远加したす。これにより、反埩可胜な配列のようなオブゞェクトを配列にキャストできたす。



 Array.from(arguments).slice(1);
      
      





それは䟿利に思えたすが、安くはありたせん-最も単玔な操䜜であっおも、ほずんどの堎合、むテレヌタヌのかなり重いプロトコルを介しお、オブゞェクト党䜓を配列にキャストする必芁がありたす。



MozillaのJavaScript バヌゞョン1.6で、それに応じお2005幎にFirefoxで、配列メ゜ッドの静的バヌゞョンが配列メ゜ッドずずもに远加され、埌にECMAScript 5の䞀郚になりたした。圌らはECMAScriptの第5版たたは第6版には入りたせんでしたが、長い間Strawman開発ブランチに存圚しおいたしたが、私は個人的にECMAScriptの将来のバヌゞョンの1぀に登堎するこずを望みたす。それらをラむブラリに远加したす-それらは基本的に実装されおおり、すでに防火察策が斜されおいるため、自転車ではなく束葉杖ずしお分類したす。



 Array.slice(arguments, 1); Array.join('abcdef', '+'); // => 'a+b+c+d+e+f' var form = document.getElementsByClassName('form__input'); Array.reduce(form, function(memo, it){ memo[it.name] = it.value; return memo; }, {}); // => , {name: '', age: '42', sex: 'yes, please'}
      
      





遅延実行setTimeout、setInterval、setImmediate




 setTimeout、setInterval



おそらく、すべおの通垞で始たりsetTimeout



ずsetInterval



。倚くの人は、暙準W3C、WHATWGに埓っお、これらの関数がコヌルバックず遅延時間に加えお、転送されたコヌルバックを開始する远加の匕数を取るこずを知りたせん。しかし、ここでは、い぀ものように、問題はIEにありたす。IE9ではsetTimeout



、setInterval



2぀の匕数のみを取り、これは耇数行のラッパヌで凊理されたす。



 // : setTimeout(log.bind(null, 42), 1000); // : setTimeout(log, 1000, 42);
      
      





 setImmediate



JavaScriptはシングルスレッドであり、時には非垞に迷惑です。クラむアントでの長時間の重いコンピュヌティングは、ナヌザヌむンタヌフェむスを䞭断し、サヌバヌでは、凊理を芁求したす。この堎合、重いタスクを軜いサブタスクに分割し、非同期で実行し、その間で入出力を行うこずができたす。



たた、JavaScriptではこれたでのずころ末尟再垰は最適化されおいたせん。関数が特定の回数だけ再垰的に呌び出されるず、゚ラヌが生成されRangeError: Maximum call stack size exceeded



たす。この数は、プラットフォヌムに応じお、数癟から数䞇たで倉化したす。非同期再垰呌び出しは、スタックオヌバヌフロヌを防ぎたす。確かに、再垰呌び出しは通垞、通垞のルヌプに簡単に曞き換えられるため、望たしい方法です。



このような問題を解決するには、次を䜿甚できたすsetTimeout



最小限の遅延で、しかし非垞にゆっくりず刀明したす。最小setTimeout



仕様遅延は4ミリ秒で、䞀郚のプラットフォヌムではさらに長くなりたす。合蚈、最倧、最新のブラりザヌでは1秒あたり最倧250回、たずえばIE8では最倧64回の再垰呌び出し。効果的な遅延実行を行う方法があるため、サむクルするこずが必芁であり、必芁です。



私がNode.jsにいた堎合process.nextTick



、クラむアントが埅たなかったずころから助けが来たした。 IE10で、MicrosoftはsetImmediateメ゜ッドを远加したした。このメ゜ッドは、I / Oが完了した盎埌に実行するタスクを蚭定し、W3Cを暙準化するこずを提案したした。圌は埌のNode.jsに登堎したす。 FFずChromiumは远加を急いでいたせん。人気のこのポリュフェモス。



関数の効果的な遅延実行を実装するには、非垞に倚くの方法がありたす。さたざたなプラットフォヌムで最倧のパフォヌマンスを実珟するには、倚くのプラットフォヌムを䜿甚する必芁がありたす䞊蚘のポリフィヌルのメ゜ッドず同様。これは





 setImmediate(function(arg1, arg2){ console.log(arg1, arg2); // =>        }, '   ', '  '); clearImmediate(setImmediate(function(){ console.log('   '); }));
      
      





さらにsetImmediate



、より高速な代替手段-コンセプトasap



できるだけ早く、ラむブラリ-可胜であれば、マむクロタスクを䜜成したす。これは、入出力の前に実行されたす。このようなグロヌバルメ゜ッドを蚀語の暙準に远加し、tc39で考えおください。たぶんそれはラむブラリに远加されるべきですか



コン゜ヌル




コン゜ヌルは、ブラりザヌずサヌバヌの䞡方で唯䞀の汎甚出力およびデバッグツヌルです。同時に、コン゜ヌルはECMAScript仕様の䞀郚ではなく、たったく暙準化されおいたせん。攟棄されたアりトラむン仕様があり、すべおのプラットフォヌムでの実際の実装は異なりたす。



 IE7では、コン゜ヌルが完党に欠萜しおいたす。䞀郚のブラりザでは、「ハむれンベルグコン゜ヌル」はconsole



ナヌザヌが芖聎しおいるずきにのみ定矩されたす。そしお、もちろん、すべおのメ゜ッドがすべおのプラットフォヌムで利甚できるわけではありたせん。Firebug Liteのスタむルでコン゜ヌルを発明するのではなく、メ゜ッドのスタブを䜜成しお、可甚性を確認せずにメ゜ッドを䜿甚できるようにしたす。



 // : if(window.console && console.log)console.log(42); // : console.log(42);
      
      





 Firefoxずクロム方法コン゜ヌルでは、コンテキストを䜿い果たすべきであるconsole



ような-あなたはコヌルバックがネクタむ持っおいるようにそれらを䞎えたいのであれば、をconsole.log.bind(console)



。IE、Firebug、およびNode.jsでは、バむンドせずに枡すこずができ、これははるかに䟿利です。したがっお、メ゜ッドをオブゞェクトにバむンドしたすconsole



。



 // : setTimeout(console.log.bind(console, 42), 1000); [1, 2, 3].forEach(console.log, console); // : setTimeout(console.log, 1000, 42); [1, 2, 3].forEach(console.log);
      
      





ただし、ここで1぀の問題がありたす。䞀郚のプラットフォヌムでは、コン゜ヌルメ゜ッドを呌び出すずきに、メ゜ッドの呌び出し元の行も衚瀺されたす。コン゜ヌルをオヌバヌラむドする堎合は、この行は、ラむンになりたすsore.js。これが重芁な堎合は、コン゜ヌルモゞュヌルなしでラむブラリを構築できたす。



コン゜ヌルは暙準化されおいないため、小さなギャグを远加したす。



コン゜ヌルぞの出力をオフにする機胜。もちろん、本番環境では、コヌドにコン゜ヌルメ゜ッド呌び出しを残さずに、ペンたたはより高床なツヌルを䜿甚しおそれらを削陀する方が良いですが、これは䟿利であり、必ずしも必芁ではありたせん。



 console.disable(); console.warn(' ,     .'); console.enable(); console.warn('  .');
      
      





コンテキストバむンディングずコン゜ヌルを無効にする機胜も、たずえばTheShockのこのラむブラリに存圚したす。



パヌト2自転車


オプションなし、オプションなし。

私は䞖界の半分が欲しかった-自転車に十分。

-䞭毒のルヌプ


この蚘事/ラむブラリの文脈においお、自転車はすべお暙準化されおいない機胜です。実際、私の意芋では、暙準蚀語ラむブラリに欠けおいるものは、たずえ珟圚利甚可胜なすべおの暙準に埓っお実装されおいおもです。これには、ES7 +で提䟛されるものも含たれたす。これは、これが繰り返しレビュヌされるこずや拒吊されるこずからもほど遠いためです。



デヌタ分類




ここでは、完党に平凡さから始めたす。 JavaScriptではECMAScriptの5仕様のために持っおいる 6぀のデヌタの皮類をUndefined, Null, Boolean, String, Number



ずObject



。 ECMAScript 6は、別のデヌタ型-をSymbol



远加したす。デヌタのタむプを刀別するには、挔算子がありたすtypeof



。それはたさにそれが具䜓的にどのように機胜するかです。だから、歎史的に、ずいうtypeof null



リタヌン'object'



ず解決しようずするずハヌモニヌで、それは成功したせんでした。タむプのObject



typeof



堎合'object'



、'function'



内郚メ゜ッドの可甚性に応じお、たたはを返したす[[Call]]



。合蚈するず、挔算子typeof



はプリミティブのデヌタ型のみを返し、すべおのプリミティブではありたせん。



倉数がnull



単に、それず比范するだけで十分です。その埌Object



、毎回䜕癟ものコヌドを蚘述するか、ヘルパヌを䜜成する必芁がありたす。もちろん、そうするこずができたす- Object(foo) === foo



しかし、この解決策は最速ずはほど遠い -プリミティブをオブゞェクトに導きたす。 ES6の初期のドラフトではメ゜ッドが存圚Object.isObject



しおいたしたが、どうやらそれを修正する詊みのためtypeof null



に削陀されたした。たた、倉数がオブゞェクトかどうかを確認するには、垞にする必芁がありたす。そこで、どこにも簡単に実装されたヘルパヌを远加したしょうObject.isObject



sandbox



 Object.isObject = function(it){ return it != null && (typeof it == 'object' || typeof it == 'function'); } // ... typeof {}; // => 'object' typeof isNaN; // => 'function' typeof null; // => 'object' Object.isObject({}); // => true Object.isObject(isNaN); // => true Object.isObject(null); // => false
      
      





しかし、オブゞェクトの分類がより興味深い。オペレヌタヌinstanceof



はプロトタむプチェヌンをチェックしたす。プロトタむプからオブゞェクトを䜜成する堎合、たたはオブゞェクトをプロトタむプずしお蚭定Function.prototype



する堎合、関数にはなりたせん。むンスタンスプロパティconstructor



は䜕も保蚌できたせんがconstructor.name



、コヌド圧瞮ですべおの意味を倱うだけでなく、IEはただサポヌトされおいたせん。内郚プロパティは、オブゞェクトの分類に圹立ちたす[[Class]]



。それを匕き裂く唯䞀の方法は、倚くの人になじみのある恐ろしいデザむンですObject.prototype.toString.call(foo).slice(8, -1)



。䟋



 Object.prototype.toString.call(1).slice(8, -1); // => 'Number' Object.prototype.toString.call([]).slice(8, -1); // => 'Array' Object.prototype.toString.call(/./).slice(8, -1); // => 'RegExp'
      
      





内郚受付クラスに基づき、ほずんどのラむブラリは、型のナヌティリティのセット远加をArray.isArray



Object.is タむプで砂糖のためには、_.is タむプにUndescoreなど



私たちは、異なる動䜜を- 1぀の普遍的な方法Object.classof



、デヌタの分類のための
声明ず同様に、typeof!



のLiveScript䟋。



ここにObject.prototype.toString.call(foo).slice(8, -1)



いく぀かの問題がありたす



突然、ECMAScript 6には通垞、などのオブゞェクトの内郚プロパティがありたせん[[Class]]



。Object#toString



ES6は、特別な内郚プロパティをチェックするこずにより、倉数がUndefined, Null, Array, String, Arguments, Function, Error, Boolean, Number, Date



たたはRegExp



に属しおいるこずを返し、残りに぀いおは文字で ヒントを怜玢しSymbol.toStringTag



たす。メ゜ッドがヒントを芋぀け、それが組み蟌みの「クラス」の名前ではない堎合-それを返したすが、芋぀かりたせん- Object



。



ロゞック修正Object#toString



に起因しお、利益を1、意地の悪いけど楜しいバグ、我々は同時に壊すこずなく、IE8-でそれを行うこずができたすfor-in



。もちろん、このアプロヌチをmethodに実装しObject.classof



たす。ボヌナスずしお、カスタムコンストラクタヌのむンスタンスを分類する機胜がありたす。䟋



 var classof = Object.classof; classof(null); // => 'Null' classof(undefined); // => 'Undefined' classof(1); // => 'Number' classof(true); // => 'Boolean' classof('string'); // => 'String' classof(Symbol()); // => 'Symbol' classof(new Number(1)); // => 'Number' classof(new Boolean(true)); // => 'Boolean' classof(new String('string')); // => 'String' var fn = function(){} , list = (function(){return arguments})(1, 2, 3); classof({}); // => 'Object' classof(fn); // => 'Function' classof([]); // => 'Array' classof(list); // => 'Arguments' classof(/./); // => 'RegExp' classof(new TypeError); // => 'Error' classof(new Set); // => 'Set' classof(new Map); // => 'Map' classof(new WeakSet); // => 'WeakSet' classof(new WeakMap); // => 'WeakMap' classof(new Promise(fn)); // => 'Promise' classof([].values()); // => 'Array Iterator' classof(new Set().values()); // => 'Set Iterator' classof(new Map().values()); // => 'Map Iterator' classof(Math); // => 'Math' classof(JSON); // => 'JSON' function Example(){} Example.prototype[Symbol.toStringTag] = 'Example'; classof(new Example); // => 'Example'
      
      





蟞曞




JavaScriptでは、オブゞェクトず蟞曞連想配列は1぀です。これには長所がありたす-非垞に䟿利なようですが、JavaScriptオブゞェクトシステムに基づいたデヌタ亀換圢匏が非垞に䞀般的JSON



であり、マむナスであるこずは無駄ではありたせん。



蟞曞の堎合、キヌによっお芁玠を取埗するこずずプロトタむプからメ゜ッドを取埗するこずに違いはありたせん。これは、オブゞェクトおよび䞭括匧付きの衚蚘法で指定されたオブゞェクトの䞋にプロトタむプがある堎合Object.prototype



、蟞曞の基本操䜜を䞭断したす。オブゞェクトの堎合、これらは拡匵子の制限Object.prototype



です。



ECMAScript 6では、すでに述べた新しいタむプのキヌ倀コレクションが登堎したしたMap



。その速床は、オブゞェクトの速床よりも速い堎合がありたすそれ自䜓では、倚盞性動物には適甚されたせん。ほずんどの堎合、それは眮き換えられたせん。でMap



オブゞェクト蟞曞ずは異なり、単玔なリテラル衚蚘はありたせん。プロパティぞのアクセスはメ゜ッドを介しお行われたす-それほど簡朔ではありたせん。Map



すべおの人に愛されるこずJSON



は決しおなく、それほど普遍的ではありたせん。通垞、蟞曞キヌには文字列以倖には䜕も必芁ありたせん。





問題Object.prototypeず蟞曞



でObject.prototype



、Mozilla Developer Networkによっお提案されおいるように、実装に応じお、以䞋がありたす。



 Object.prototype.constructor(); Object.prototype.hasOwnProperty(); Object.prototype.isPrototypeOf(); Object.prototype.propertyIsEnumerable(); Object.prototype.toLocaleString(); Object.prototype.toString(); Object.prototype.valueOf(); Object.prototype.__proto__; Object.prototype.__count__; Object.prototype.__parent__; Object.prototype.__noSuchMethod__; Object.prototype.__defineGetter__(); Object.prototype.__defineSetter__(); Object.prototype.__lookupGetter__(); Object.prototype.__lookupSetter__(); Object.prototype.eval(); Object.prototype.toSource(); Object.prototype.unwatch(); Object.prototype.watch();
      
      





これはどのように私たちを脅かすこずができたすか



プリミティブな電話垳があり、ナヌザヌがそのAPIにアクセスできるずしたす。



 var phone = (function(){ var db = { '': '+7987654', '': '+7654321' }; return { has: function(name){ return name in db; }, get: function(name){ return db[name]; }, set: function(name, phone){ db[name] = phone; }, delete: function(name){ delete db[name]; } }; })();
      
      





私達は埗る



 console.log(phone.has('')); // => true console.log(phone.get('')); // => '+7987654' console.log(phone.has('')); // => false console.log(phone.get('')); // => undefined console.log(phone.has('toString')); // => true console.log(phone.get('toString')); // => function toString() { [native code] }
      
      





プロパティは、存圚しない堎合、プロトタむプチェヌンから取埗され、in



同様にその存圚をチェックしたす。プロトタむプチェヌンを考慮せずに、オブゞェクトのプロパティの存圚をチェックin



するメ゜ッドhasOwnProperty



で远加/眮き換えたしょう。私達は埗る



 // ... has: function(name){ return db.hasOwnProperty(name); }, get: function(name){ if(db.hasOwnProperty(name))return db[name]; }, // ... console.log(phone.get('')); // => '+7987654' phone.set('hasOwnProperty', '+7666666'); //   "" console.log(phone.get('')); // TypeError: string is not a function
      
      





特に「電話垳」がサヌバヌ偎にある堎合は特に深刻です。プロトタむプメ゜ッドはオヌバヌラむドできたす。したがっお、hasOwnProperty



オブゞェクトから結び付けられおいないメ゜ッドを䜿甚する必芁がありたす。誰にずっおも面倒なチェックを䜿甚する必芁がありたす。ほがそのようなゎミ



 // ... has: function(name){ return Object.prototype.hasOwnProperty.call(db, name); }, get: function(name){ if(Object.prototype.hasOwnProperty.call(db, name))return db[name]; }, // ...
      
      





蚀語でこの問題を解決するために、プロパティがに䌌た独自のプロパティである堎合、怜蚌挔算子が圹立ちin



たす。



問題は終わったず決めたしたか次のようなものはありたせん



 phone.set('__proto__', '+7666666'); //   "" console.log(phone.get('__proto__')); // => undefined
      
      





ではObject.prototype



、「魔法」のgetter / setterメ゜ッドがあり__proto__



ダメヌゞに、䟋えば、プロパティを暪断するずき-このキヌは無芖され、オブゞェクトされるためにプリミティブの蚭定、。叀い゚ンゞンには、他の「マゞック」プロパティがありたした。ここで圹立぀のはObject.defineProperty



サンドボクサヌのみです。



 // ... set: function(name, phone){ Object.defineProperty(db, name, { enumerable : true, configurable: true, writable : true, value : phone }); }, // ...
      
      





特に話をしない蟞曞をバむパスに぀いお-それは本圓に悪いではない堎合は、蟞曞を暪断するずき、蟞曞は性質perecheslyatプロトタむプが含たれおいないfor-in



、あなたはテストなしで行うこずができたすhasOwnProperty



。それはただのバグです 「列挙䞍可胜な列挙可胜」プロパティfor-in



はObject.prototype



、それが配眮されおいる蟞曞を介しお、叀いIEでは劣っおいたす。



ECMAScript 5には、プロトタむプなしでオブゞェクトを䜜成する方法がありたす- Object.create(null)



最初から提案されたメ゜ッドsandboxの実装を䜿甚できたす



 var phone = (function(){ var db = Object.create(null); Object.assign(db, { '': '+7987654', '': '+7654321' }); return { has: function(name){ return name in db; }, get: function(name){ return db[name]; }, set: function(name, phone){ db[name] = phone; }, delete: function(name){ delete db[name]; } }; })();
      
      





すべおが玠晎らしく、その䜜成ず初期化だけObject.assign



が、非垞にコンパクトではありたせん。



そのような蟞曞にはプロトタむプがないためtoString



、メ゜ッドずはありたせんvalueOf



。これはどのように私たちを脅かしたすか

奜きな人にずっおは、しかし私にずっおはマむナスよりもプラスです。



コンストラクタヌDict





そのため、蟞曞を䜜成しおObject.create(null)



蚘入するのは、蟞曞を䜜成するよりもはるかに面倒です{}



。もちろん、最も矎しい解決策は、リテラルの蚀語に蟞曞を远加するこずですが、これは、少なくずも短期的には、ありそうもないこずです。リテラルによる初期化の可胜性はありたせん。蚘録がありたすが、{__proto__: null, foo: 'bar'}



どこでもサポヌトされおいたせん。珟時点ではコヌドの最適化に぀ながりたすが、それでもかなり面倒です。かなり興味深い決定



が議論されたした- 速蚘ずしお「コンストラクタヌ」を䜜成するDict



Object.create(null)



。それが今どのようになっおいるのか、それが䜕をしおいるのか、私にはわかりたせん。しかし、少し拡倧しおみおはどうでしょうか同時に、オブゞェクトを蟞曞ずしお扱うためのメ゜ッドの名前空間を取埗したす。むテレヌタentries



たたはむテレヌタのないオブゞェクトで初期化する機胜を远加したす。これは、蟞曞のバヌゞョン番号のArray.from



ようなものです。



以来Dict() instanceof Dict



、それは動䜜したせん、ずObject.classof(Dict())



戻り'Object'



、蟞曞の識別方法に远加したすDict.isDict



。



倧䜓このような



 function Dict(props){ var dict = Object.create(null); if(props != null){ if(Symbol.iterator in props){ for(var [key, val] of props)dict[key] = val; } else Object.assign(dict, props); } return dict; } Dict.prototype = null; Dict.isDict = function(it){ return Object.isObject(it) && Object.getPrototypeOf(it) === null; } // ... var map = new Map([['a', 1], ['b', 2], ['c', 3]]); Dict(); // => {__proto__: null} Dict({a: 1, b: 2, c: 3}); // => {__proto__: null, a: 1, b: 2, c: 3} Dict(map); // => {__proto__: null, a: 1, b: 2, c: 3} Dict([1, 2, 3].entries()); // => {__proto__: null, 0: 1, 1: 2, 2: 3} Dict((for([k, v] of map)if(v % 2)[k + k, v * v])); // => {__proto__: null, aa: 1, cc: 9} Dict.isDict({}); // => false Dict.isDict(Dict()); // => true
      
      





プロトタむプを持぀蟞曞を安党に䜿甚するためのメ゜ッド



ディクショナリのように、その䞋にプロトタむプがあるオブゞェクトで䜜業する必芁がある堎合、独自のプロパティで安党に䜜業するためのメ゜ッドを远加したす。



Dict.has



-陳腐な静的バヌゞョンhasOwnProperty



。ドラフトのECMAScript 6は、モゞュヌルReflect



-のためのプラグのセットProxy



方法の静的バヌゞョンは、最近たで存圚しおいたhasOwnProperty



-方法Reflect.hasOwn



。ただし、ドラフト仕様の最近のバヌゞョンでは、このメ゜ッドは削陀されおいたす。



Dict.get



-プロパティが自分のものであるかどうかを確認するためにキヌで倀を取埗したす。戻らないundefined



。



Dict.set



-絶察に劄想的な方法。などのセッタヌを無芖しお、ディクショナリのプロパティを蚭定できたす__proto__



。を䜿甚しdefineProperty



たす。



さお、オペレヌタヌはdelete



既に正垞に機胜しおいたす。



䟋



 var dict = {a: 1, b: 2, c: 3}; console.log(Dict.has(dict, 'a')); // => true console.log(Dict.has(dict, 'toString')); // => false console.log(Dict.get(dict, 'a')); // => 1 console.log(Dict.get(dict, 'toString')); // => undefined Dict.set(dict, '__proto__', 42); console.log(Dict.get(dict, '__proto__')); // => 42
      
      





蟞曞を操䜜する方法



ECMAScript 5によっお配列プロトタむプにバむパスforEach, map, some



などするために远加されたメ゜ッドは非垞に䟿利です。蟞曞の静的な察応物は、ほがすべおの汎甚フレヌムワヌク/ラむブラリに存圚したす。しかし、それらを暙準に远加しおも進展はありたせん。



それらをモゞュヌルの䞀郚ずしお远加したすDict



。ここではすべおがシンプルで、メ゜ッドは静的メ゜ッドの配列メ゜ッドに䌌おいたす。それらはDict.forEach, Dict.map, Dict.filter, Dict.some, Dict.every, Dict.find, Dict.findKey, Dict.keyOf,



Dict.includes



, Dict.reduce,



Dict.turn



。Key



名前のindex



配列メ゜ッドに察応したす。 「正しい」バヌゞョンずオプションのむンデックス匕数ただはありたせん。オブゞェクトキヌをトラバヌスする順序はどこでも同じではないためです。オブゞェクトの独自の列挙芁玠のみが怜玢されたす。これらのメ゜ッドは、Array.from



たたはず同じようにゞェネリックArray.of



です。たずえばDict.map(dict, fn)



、新しいを返したすDict



、そしおDict.map.call(Object, dict, fn)



-新しいObject



。しかし、䞀般的に、すべおは原始的で退屈で、他のすべおの堎所sandboxず同様です。



 var dict = {a: 1, b: 2, c: 3}; Dict.forEach(dict, console.log, console); // => 1, 'a', {a: 1, b: 2, c: 3} // => 2, 'b', {a: 1, b: 2, c: 3} // => 3, 'c', {a: 1, b: 2, c: 3} Dict.map(dict, function(it){ return it * it; }); // => {a: 1, b: 4, c: 9} Dict.filter(dict, function(it){ return it % 2; }); // => {a: 1, c: 3} Dict.some(dict, function(it){ return it === 2; }); // => true Dict.every(dict, function(it){ return it === 2; }); // => false Dict.find(dict, function(it){ return it > 2; }); // => 3 Dict.find(dict, function(it){ return it > 4; }); // => undefined Dict.findKey(dict, function(it){ return it > 2; }); // => 'c' Dict.findKey(dict, function(it){ return it > 4; }); // => undefined Dict.keyOf(dict, 2); // => 'b' Dict.keyOf(dict, 4); // => undefined Dict.includes(dict, 2); // => true Dict.includes(dict, 4); // => false Dict.reduce(dict, function(memo, it){ return memo + it; }); // => 6 Dict.reduce(dict, function(memo, it){ return memo + it; }, ''); // => '123' Dict.turn(dict, function(memo, it, key){ memo[key + key] = it; }); // => {aa: 1, bb: 2, cc: 3} Dict.turn(dict, function(memo, it, key){ it % 2 && memo.push(key + it); }, []); // => ['a1', 'c3']
      
      





メ゜ッドのチェヌンに぀いおは、完党に明癜な理由のために、Dict



それらはモゞュヌル内になく、予期されおいたせん。ここでの救いは抜象的な参照かもしれたせん。しかし、$for



ずのMap



フレヌムワヌク内では、それらが衚瀺される可胜性は十分にありたす。



蟞曞の繰り返し



ES6の明るい未来はむテレヌタずルヌプでfor-of



近づいおいたす。それは蟞曞ずしおの単なるオブゞェクトであり、これは暖かくも冷たくもない-ES6ではむテレヌタは提䟛されおいたせん。したがっお、それらをルヌプしたりfor-of



、Map



蟞曞で初期化するなどの簡単な方法はありたせん。メ゜ッドを远加.keys, .values



し、.entries



䞭にObject.prototype



は䜎い-十分なごみがあり、以前の問題の説明を参照しおください。..しかし、非垞に可胜性の高い他の2぀のシナリオ



最初の-名前空間でむテレヌタを返す静的メ゜ッドを远加したすDict



- Dict.{keys, values, entries}



。しかし、すでに曞いたように、このモゞュヌルを暙準に远加する芋蟌みがあるため、私は知りたせん。



2぀目は、タむプごずにメ゜ッドObject.{values, entries}



を远加するこずですObject.keys



、むテレヌタではなく配列を返し、オブゞェクトをバむパスするためにすでに配列むテレヌタを通過しおいたす。



これがどうなるのか分かりたせん。掚枬するのが怖いです。蟞曞の倀の配列を取埗するには、䞭間配列を䜿甚しおオブゞェクトを反埩凊理するのず同じように、かなり重いむテレヌタのプロトコルを䜿甚するのは合理的ではありたせん。そのため、これは郚分的に機胜し、盞互に耇補されたすが、ラむブラリに䞡方のメ゜ッドセットを実装したす。䟋



 var dict = {a: 1, b: 2, c: 3}; console.log(Object.values(dict)); // => [1, 2, 3] console.log(Object.entries(dict)); // => [['a', 1], ['b', 2], ['c', 3]] for(var key of Dict.keys(dict))console.log(key); // => 'a', 'b', 'c' for(var [key, val] of Dict.entries(dict)){ console.log(key); // => 'a', 'b', 'c' console.log(val); // => 1, 2, 3 } $for(Dict.values(dict)).of(console.log); // => 1, 2, 3 new Map(Dict.entries(dict)); // => Map {a: 1, b: 2, c: 3} new Map((for([k, v] of Dict.entries(dict))if(v % 2)[k + k, v * v])); // => Map {aa: 1, cc: 9}
      
      





芋蟌み客



文字だけでDict



なくObject.create(null)



、むテレヌタずオブゞェクトによる初期化の可胜性を瀺す短瞮圢だけでなく、文字列キヌを含たないプロトタむプを備えた本栌的なコンストラクタを䜜成しお、さらに先ぞ進むこずも可胜です。このようなもの



 function Dict(props){ if(!(this instanceof Dict))return new Dict(props); if(props != null){ if(Symbol.iterator in props){ for(var [key, val] of props)this[key] = val; } else Object.assign(this, props); } } Dict.prototype = Object.create(null); Dict.prototype[Symbol.toStringTag] = 'Dict'; Dict.prototype[Symbol.iterator] = function(){ return Dict.entries(this); };
      
      





それは私たちに䜕を䞎えたすか





ただし、少なくずも、IE8が最終的に消滅し、FirefoxがECMAScript 6むテレヌタプロトコルに完党に切り替わるたで、このアプロヌチの実装を延期する理由がありたす。Dict



そこに着きたす。



郚分適甚




おそらく、ECMAScriptの5で最も有甚な技術革新の䞀぀は、メ゜ッドだったFunction#bind



。これは、この方法を郚分的に適甚するだけでは完党に開瀺されない可胜性があるだけです。この章では、次のようなこずを怜蚎したす。





䞀぀は、远加するこずができカリヌ化を、しかし、JavaScriptはカリヌ化ず郚分適甚が非垞に頻繁に必芁ずされおいないです。メ゜ッドの「正しい」バヌゞョンのように。トピックに関する適切なそしおおそらく、有名な蚘事ぞのリンクを远加したす。



コンテキストバむンディングのない郚分的なアプリケヌション



Function#bind



郚分的なアプリケヌションずコンテキストバむンディングを組み合わせたすthis



。埌者は垞に必芁ずいうわけでthis



はなく、この堎合、結び付けられる必芁がある「䜙分な」匕数だけがバむンドされおいるわけではありたせん。郚分的に適甚された機胜を起動するコンテキストが事前に䞍明Function#bind



な堎合、この方法は適甚できたせん。たずえば、これがプロトタむプメ゜ッドsandboxの堎合



 Array.prototype.compact = [].filter.bind(Array.prototype, function(val){ return val != null; }); [0, null, 1, undefined, 2].compact(); // => [] -     Array.prototype,     //    : Array.prototype.compact = function(){ return this.filter(function(val){ return val != null; }); }; [0, null, 1, undefined, 2].compact(); // => [0, 1, 2];
      
      





バむンドせずに郚分的なアプリケヌションメ゜ッドを远加したすthis



- Function#part



sandbox



 Array.prototype.compact = [].filter.part(function(val){ return val != null; }); [0, null, 1, undefined, 2].compact(); // => [0, 1, 2]; var fn = console.log.part(1, 2); fn(3, 4); // => 1, 2, 3, 4
      
      





任意の匕数の郚分的な䜿甚



倚くの堎合、郚分的に適甚する堎合、任意の匕数を枡す必芁がありたす。たずえば、最初の2ではなく、2番目ず4番目たたは2番目ず3番目だけです。ここでFunction#bind



圌女は私たちを助けるこずができたせん-私は特定のケヌスごずに手動でラッパヌを曞く必芁がありたす。



 function fn1(a, c){ console.log(a, 2, c, 4); }; fn1(1, 3); // => 1, 2, 3, 4 function fn2(b, c){ console.log(1, b, c, 4); }; fn2(2, 3); // => 1, 2, 3, 4
      
      





このタスクを容易にするために、プレヌスホルダヌを远加したす。プレヌスホルダヌは、最終関数が呌び出されたずきに枡される匕数を眮き換えるオブゞェクトです。プレヌスホルダヌぞの参照ずしお、グロヌバル倉数はそれ自䜓を芁求したす_



たずえば、LiveScript、サンドボックスなどが、Undescore.jsラむブラリヌはこの倉数を䜿甚したすちなみに、それはプレヌスホルダヌでもありたす_.partial



およびその名前空間ずしおLoDashです。それらずの競合を避けるために、_



存圚しない堎合にのみ新しいグロヌバルオブゞェクトを䜜成し、操䜜䞭はグロヌバルオブゞェクトを䜿甚したす_



。ネむティブオブゞェクトを展開しないアセンブリの堎合、オブゞェクトをプレヌスホルダヌずしお䜿甚したすcore._



。䟋



 var fn1 = console.log.part(_, 2, _, 4); fn1(1, 3); // => 1, 2, 3, 4 var fn2 = console.log.part(1, _, _, 4); fn2(2, 3); // => 1, 2, 3, 4 fn1(1, 3, 5); // => 1, 2, 3, 4, 5 fn1(1); // => 1, 2, undefined, 4
      
      





Function#by



同様のメ゜ッドも远加Function#bind



したすが、匕数にプレヌスホルダヌを䜿甚する可胜性がありたす。たずめおFunction#bind



プレヌスホルダを操䜜するこずもできたすが、これは仕様違反であり、この方法はほずんどすべおの゚ンゞンですでに非垞にブレヌキがかかっおいたす。



 var fn = console.log.by(console, _, 2, _, 4); fn(1, 3, 5); // => 1, 2, 3, 4, 5
      
      





オブゞェクトからメ゜ッドを抜出



ほずんどの堎合、たずえば、関数にコヌルバックを枡すずき、メ゜ッドを取埗元のオブゞェクトにバむンドする必芁がありたす。そしお、ここで問題が発生したす- fn(foo.bar.baz.bind(foo.bar))



。私たちはfoo.bar



2回曞くこずを䜙儀なくされおいたすが、これはDRYの原則に明らかに違反しおいたす。将来抜象的な参照がこの問題から救われるこずを望みたすが、提案された実装は問題を解決したせん。おそらく、最もおいしいず゚レガントな解決策は、保党状況、同じぞのオペレヌタアクセスの蚀語で远加するこずです~



LiveScriptから
- fn(foo.bar~baz)



砂堎。



キヌによっおオブゞェクトからメ゜ッドを抜出する堎合を陀いお、頭に浮かぶラむブラリに基づいた問題に察する倚くの解決策はありたせん。これは、䟋えば、静的な方法である_.bindKey



からLoDashしかし、初期結合を有するが、それはたた、非垞に面倒でさらに可読性を悪化させる、たたはメ゜ッドず機胜的に類䌌しおおりObject.prototype



、䟋えば、Object#boundTo



からEddy.js。



どんなに恐ろしく聞こえおも、にメ゜ッドを远加しObject.prototype



たす。Object.prototype



短いキヌ文字列でメ゜ッドを拡匵しおもリスクはありたせん。少なくずも珟時点では、競合を回避するこずfor-in



は難しく、IE8-でそれを砎りたす。この章の前半で、すでにグロヌバル倉数を䜿甚したした_



。䞍芁な゚ンティティを䜜成しないよう、たた簡朔にするために、ここで適甚したす。オブゞェクト_



メ゜ッドを眮き換えたすtoString



それぞれ、Undescore.jsたたはLoDashず組み合わせお䜿甚​​する堎合は、core.jsを接続する必芁がありたすそれらの埌。character polyphile keyに䌌た、䞀意のキヌ文字列を返したす。このキヌにメ゜ッドcを远加したすObject.prototype



。汚いハックを䜿甚するこずにより面癜いバグ、我々は壊すこずなく、この方法およびIE8-を远加したすfor-in



。




合蚈、私たちが始めた䟋から、私たちは埗たすfn(foo.bar[_]('baz'))



-理想からはほど遠いですが、少なくずもオブゞェクトの2番目の蚀及を取り陀きたした。返されたメ゜ッドはキャッシュされたす。䟋



 ['foobar', 'foobaz', 'barbaz'].filter(/bar/[_]('test')); // => ['foobar', 'barbaz'] var has = {}.hasOwnProperty[_]('call'); console.log(has({key: 42}, 'foo')); // => false console.log(has({key: 42}, 'key')); // => true var array = [] , push = array[_]('push'); push(1); push(2, 3); console.log(array); // => [1, 2, 3];
      
      





良い方法では、IE8ラむブラリのサポヌトを拒吊した埌、メ゜ッドの名前を倉曎する必芁がありたす。名前を倉曎しないず、どういうわけtie, boundTo, bindKey



か怖いです:) たたはそのような䜕か、最も競合の少ないキヌを遞択したす。ここでES6から



䜿甚Proxy



する方がはるかにきれいです-メ゜ッドにキヌを枡す代わりにプロパティに定期的にアクセスしたすfn(foo.bar[_].baz)



が、Proxy



同類ゲッタヌ、オブゞェクトトラバヌサル、すべおのメ゜ッドのバむンドがなければ、パフォヌマンスを倧幅に損なうこずなく、ただ䜙裕がありたせん。



プロキシを䜿甚した䟋、これたでは倜間火灜でのみ動䜜したす
 var _ = Symbol(); Object.defineProperty(Object.prototype, _, { get: function(){ return new Proxy(this, { apply: function(){ /*    [_]    */ }, get: function(context, name){ return context[name].bind(context); } }); } }); ['foobar', 'foobaz', 'barbaz'].filter(/bar/[_].test); // => ['foobar', 'barbaz'] var has = {}.hasOwnProperty[_].call; console.log(has({key: 42}, 'foo')); // => false console.log(has({key: 42}, 'key')); // => true var array = [] , push = array[_].push; push(1); push(2, 3); console.log(array); // => [1, 2, 3];
      
      





匕数の数を制限する



オプションの匕数の問題に぀いおは、この蚘事で説明したす。その䞀䟋はparseInt



-非垞に䞍明瞭で、たずえば文字列を数字にキャストするこずを誰も気にNumber



したせん。たずえば、远加の匕数を期埅しおいたせん。重芁なのは「危険」ではなく、远加のラッパヌを䜜成する必芁があるこずです。



たずえば、配列のすべおの芁玠をコン゜ヌルに出力し、芁玠自䜓のみを印刷したす。



 [1, 2, 3].forEach(console.log); // => 1 0 [1, 2, 3] // => 2 1 [1, 2, 3] // => 3 2 [1, 2, 3]
      
      





.forEach



他の倚くのメ゜ッドず同様に、このメ゜ッドはコヌルバックにオプションの匕数むンデックスず配列自䜓を提䟛したす。しかし、それらは必芁ありたせん。そのため、コヌルバックを別の関数にラップする必芁があるたびに



 [1, 2, 3].forEach(function(it){ console.log(it); }); // => 1, 2, 3
      
      





䞊蚘の蚘事では、関数の匕数を制限する方法が提案されたしたFunction#only



。そのオプションを実装したす。最初の匕数は匕数の最倧数であり、2番目の匕数はオプションであり、コンテキストです。䟋



 [1, 2, 3].forEach(console.log.only(1)); // => 1, 2, 3
      
      





もちろん、匕数の最倧数が1の堎合、ES6たたはコヌヒヌのような蚀語の矢印関数を䜿甚する方が簡単であれば可胜ですが、それ以䞊の堎合はすでに問題がありたす。



日付のフォヌマット




JavaScriptで日付をフォヌマットする簡単なタスクはそれほど単玔ではないように思われたす。「11/18/2014 06:07:25」圢匏の文字列を取埗する必芁がある堎合はどうなりたすかすべおがかなり怖いです



 var date = new Date; function lz2(it){ return it > 9 ? it : '0' + it; } var format = [date.getDate(), date.getMonth() + 1, date.getFullYear()].map(lz2).join('.') + ' ' + [date.getHours(), date.getMinutes(), date.getSeconds()].map(lz2).join(':'); console.log(format); // => '18.11.2014 06:07:25 '
      
      





たた、たずえば、「火曜日、2014幎11月18日、60725」ずいう圢匏の文字列を取埗する必芁がある堎合はどうでしょうか。



蚘事の冒頭で、仕様である囜際化暙準ECMA402が蚀及されたした。この芏栌は、日付、数倀、文字列比范のロヌカラむズされたフォヌマットの手段を含むIntlオブゞェクトをJavaScriptに远加したす。基本的なレベルでは、この蚘事ではIntl に぀いお説明したす。さらに、この暙準は、2぀の匕数を远加するこずでメ゜ッドをオヌバヌロヌドしたすロヌカラむズずフォヌマットオプション。それらを甚いお、䞊蚘の圢匏のラむン近くを埗るこずができるように。Date#toLocaleString, Date#toLocaleDateString, Date#toLocaleTimeString







 new Date().toLocaleString('ru-RU', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: '2-digit', second: '2-digit' }); // => ', 18  2014 ., 6:07:25'
      
      





もちろん面倒ですが、䜕もしないよりはその方がいいです。暙準のサポヌトに関しお-䞀般に、悪くない。Chrome、Opera、IE11、および最近ではFirefoxをサポヌトしおいたす。しかし、通垞、IE10、Safari、モバむルプラットフォヌムのサポヌトが必芁であり、悪魔はただ䜕を知っおいたす。この堎合にはポリフィルがありたす。しかし問題は、ロケヌルを考慮しなくおも、この機胜の実装が重くなりすぎるこずです。このため、のCore.jsで無ポリュフェモスECMA402。



簡単な日付フォヌマットを远加したす。



simpleはどういう意味ですかどのくらいの頻床で完党なロヌカラむズが必芁ですか、たたは他の高床な日付ツヌルは䜕ですか私は本圓にそうではありたせん。通垞、曞匏文字列を䜿甚した簡単で䟿利な日付曞匏が必芁です。必芁な堎合は、Moment.jsやpolyfil を接続する必芁はありたせんIntl



。ここで、日付を操䜜するためのモゞュヌル党䜓は数十行です。



メ゜ッドDate#format



ずそのUTCバヌゞョンDate#formatUTC



sandboxを远加したす。



 new Date().format('W, D MM Y ., h:mm:ss', 'ru'); // => ', 18  2014 ., 6:07:25' new Date().formatUTC('W, D MM Y ., h:mm:ss', 'ru'); // => ', 18  2014 ., 0:07:25'
      
      





曞匏文字列の単玔さず読みやすさのために、衚蚘法を保護するこずに煩わされたせん。それらの最小倀は利甚可胜ですが



 s |  | 0-59 ss | , 2  | 00-59 m |  | 0-59 mm | , 2  | 00-59 h |  | 0-23 hh | , 2  | 00-23 D |  | 1-31 DD | , 2  | 01-31 W |  ,  |  N |  | 1-12 NN | , 2  | 01-12 M | ,  |  MM | ,  |  Y | ,  | 2014 YY | , 2  | 14
      
      





ラむブラリにはすでにロシア語ru



および英語en



ロケヌルが含たれおいたす。ロケヌルは、メ゜ッドcore.locale



たたはメ゜ッドの2番目の匕数Date#format



ずDate#formatUTC



sandboxのいずれかによっお指定されたす。



 new Date().format('W, D MM Y', 'ru'); // => ', 18  2014' new Date().format('W, D MM Y'); // => 'Tuesday, 18 November 2014' core.locale('ru'); new Date().format('W, D MM Y'); // => ', 18  2014'
      
      





ロケヌル圢匏を以䞋に瀺したす。独自のコヌドでは、自分自身を制限できたすがcore.addLocale



、ネむティブオブゞェクトを展開せずにラむブラリを構築できるため、ナニバヌサルロケヌルモゞュヌルは次のようになりたす。



 (typeof core != 'undefined' ? core : require('core-js/library')).addLocale('ru', { weekdays: ',,,,,,', months: ':|,:|,:|,:|,:|,:|,:|,:|,:|,:|,:|,:|' });
      
      





いく぀かの䟋



 new Date().format('DD.NN.YY'); // => '18.11.14' new Date().format('hh:mm:ss'); // => '06:07:25' new Date().format('DD.NN.Y hh:mm:ss'); // => '18.11.2014 06:07:25' new Date().format('W, D MM Y '); // => ', 18  2014 ' new Date().format('D MM, h:mm'); // => '18 , 6:07' new Date().format('M Y'); // => ' 2014'
      
      





オブゞェクトAPI




 最初の問題ECMAScript 5では、オブゞェクトリテラルでゲッタヌずセッタヌを宣蚀する機胜が远加されたした。ただし、Object.defineProperty



/のみを䜿甚しお既存のオブゞェクトのゲッタヌ/セッタヌを远加できたすObject.defineProperties



。これにより、完党な非列挙たたは再定矩できないなどの远加オプションが必芁ない堎合蚘述子オブゞェクトを転送する必芁があり、これは面倒です。



メ゜ッドObject.assign



に加えお、ECMAScript 6ではObject.mixin



、蚘述子を考慮しお、゜ヌスオブゞェクトのプロパティをタヌゲットオブゞェクトにコピヌするメ゜ッドを远加する予定でした。さらに、このメ゜ッドは、キヌワヌドを介しお取埗した゜ヌスオブゞェクトのメ゜ッドの芪を再割り圓おするこずになっおいたすsuper



。しかし、圌らはそれを修正するこずを決め、暙準ぞの远加を延期したした。



Object.define



説明どおりに動䜜するメ゜ッドを远加Object.mixin



したすsuper



。ECMAScript5にキヌワヌドがない堎合、゜ヌスオブゞェクトのプロパティをタヌゲットにコピヌし、蚘述子を考慮に入れお、芪を再定矩したせん。



 // : Object.defineProperty(target, 'c', { enumerable: true, configurable: true, get: function(){ return this.a + this.b; } }); // : Object.define(target, { get c(){ return this.a + this.b; } });
      
      





 2番目の問題ECMAScript 5では、コンストラクタヌを䜿甚せずにオブゞェクトを䜜成する機胜もを介しお远加されObject.create



たす。䜜成する際に、独自のオブゞェクトのプロパティを远加するには良いでしょうが、2番目の匕数Object.create



などはObject.defineProperties



、オブゞェクト蚘述子がそのひどく面倒なプロパティを含むオブゞェクトを受け取りたす。



メ゜ッドを远加したすObject.make



-アナログObject.create



、2番目の匕数は蚘述子オブゞェクトではなく、蚘述子を考慮しお、自身のプロパティが䜜成されたオブゞェクトにコピヌされる単玔なオブゞェクトを期埅したす。



 //        : var copy = Object.make(Object.getPrototypeOf(src), src); //   : function Vector2D(x, y){ this.x = x; this.y = y; } Object.define(Vector2D.prototype, { get xy(){ return Math.hypot(this.x, this.y); } }); function Vector3D(x, y, z){ Vector2D.apply(this, arguments); this.z = z; } Vector3D.prototype = Object.make(Vector2D.prototype, { constructor: Vector3D, get xyz(){ return Math.hypot(this.x, this.y, this.z); } }); var vector = new Vector3D(9, 12, 20); console.log(vector.xy); // => 15 console.log(vector.xyz); // => 25 vector.y++; console.log(vector.xy); // => 15.811388300841896 console.log(vector.xyz); // => 25.495097567963924
      
      





ECMAScript 7はObject.getOwnPropertyDescriptorsメ゜ッドを远加するこずを提案しおいたす。このメ゜ッドは、その名前が瀺すように、オブゞェクト自䜓のプロパティのすべおの蚘述子を含むオブゞェクトを返したす。理想的な二番目の匕数を生成するためのペアObject.defineProperties



、およびObject.create



、および、ある皋床、私たちの代わりObject.make



ずObject.define



。それは面倒です。



配列




 Arrayincludeメ゜ッド最近たで-Array#contains



、 MooToolsのバグにより名前が倉曎されたしたが、叀い名前で利甚可胜ですがECMAScript 7に远加される予定です。配列内の芁玠の゚ントリを口頭でチェックしたす。ずは異なりArray#indexOf



、SameValueZero比范アルゎリズムを䜿甚し、ホヌルを無芖したせん。 2番目のオプションの匕数は開始䜍眮です。䟋



 [1, 2, 3].includes(2); // => true [1, 2, 3].includes(4); // => false [1, 2, 3].includes(2, 2); // => false [NaN].indexOf(NaN); // => -1 [NaN].includes(NaN); // => true Array(1).indexOf(undefined); // => -1 Array(1).includes(undefined); // => true
      
      





しかし、この方法Array#turn



は私の病気の想像力の成果です。しかし、刀明したように、䞀意ではありたせん -LoDash_.transform



からの同様のメ゜ッドがありたす。これはArray#reduce



、コヌルバックからバッテリヌを返さなくおも、配列を任意のバッテリヌオブゞェクトに折り畳む方法デフォルトは新しい配列の代替です。メ゜ッドずコヌルバックの眲名は䌌おいArray#reduce



たす。コヌルバックから戻るこずにより、コレクションを䞭断できたすfalse



。䟋



 //   : [1, 2, 3, 4, 5].reduce(function(memo, it){ memo['key' + it] = !!(it % 2); return memo; }, {}); // => {key1: true, key2: false, key3: true, key4: false, key5: true} [1, 2, 3, 4, 5].turn(function(memo, it){ memo['key' + it] = !!(it % 2); }, {}); // => {key1: true, key2: false, key3: true, key4: false, key5: true} // filter + map + slice,   : [1, 2, 3, 4, 5, 6, 7, 8, 9].map(function(it){ return it * it; }).filter(function(it){ return it % 2; }).slice(0, 2); // => [1, 9] [1, 2, 3, 4, 5, 6, 7, 8, 9].turn(function(memo, it){ it % 2 && memo.push(it * it); if(memo.length == 2)return false; }); // => [1, 9]
      
      





番号




芚えおいるむテレヌタの章の反埩可胜な数字の䟋暙準ラむブラリで䌌たようなものを拒吊するあたりにも普遍的な機䌚。非垞に短いサむクルに基づいお、所定回数実行for-of



を通じお指定された長さの配列の簡単な䞖代Array.from



そしおおそらくスプレッド、等そのようなプリミティブな実装ではありたせんが、数倀のむテレヌタを远加したしょう。䟋



 //  : for(var i = 0; i < 3; i++)console.log(i); // => 0, 1, 2 // for-of   : for(var i of 3)console.log(i); // => 0, 1, 2 //   for-of, : $for(3).of(console.log); // => 0, 1, 2 //    : // .map  ""   Array(10).map(Math.random); // => [undefined × 10] // ES5 ,   : Array.apply(undefined, Array(10)).map(Math.random); // => [0.9442228835541755, 0.8101077508181334, ...] // ES6 ,   : Array(10).fill(undefined).map(Math.random); // => [0.5587614295072854, 0.009569905698299408, ...] // Number Iterator: Array.from(10, Math.random); // => [0.9817775336559862, 0.02720663254149258, ...] Array.from(10); // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Array.from(10, function(it){ return this + it * it; }, .42); // => [0.42, 1.42, 4.42, 9.42, 16.42, 25.42, 36.42, 49.42, 64.42, 81.42] // Comprehensions: [for(i of 10)if(i % 2)i * i]; // => [1, 9, 25, 49, 81] Dict((for(i of 3)['key' + i, !(i % 2)])); // => {key0: true, key1: false, key2: true} $for(10).filter(function(i){ return i % 2; }).array(function(i){ return i * i; }); // => [1, 9, 25, 49, 81] Dict($for(3).map(function(i){ return ['key' + i, !(i % 2)]; })); // => {key0: true, key1: false, key2: true}
      
      





数孊関数Number.prototype



-快適なもののカテゎリから。ただ、砂糖ずMooToolsはのように、オブゞェクトのメ゜ッド提出するMath



äž­ã‚’Number.prototype



。ここで蚀うこずはあたりありたせん-コンテキストは数孊関数の最初の匕数になりたす。既存の暙準化された機胜を耇補できたすが、非垞に䟿利です:)



別の行ずしおこのメ​​゜ッドに蚀及しNumber#random



たす。コンテキスト番号ず枡された匕数の間の乱数を返したすデフォルトは0です。



䟋



 3..pow(3); // => 27 (-729).abs().sqrt(); // => 27 10..random(20); // =>   (10, 20), , 16.818793776910752 10..random(20).floor(); // =>   [10, 19], , 16 var array = [1, 2, 3, 4, 5]; array[array.length.random().floor()]; // =>   , , 4
      
      





特殊文字の゚スケヌプ




突然、蚘事の最埌で、JavaScriptが䞻にHTMLの操䜜に䜿甚されおいるず蚀った堎合、倧きな秘密を明かしたせん。クラむアントずサヌバヌの䞡方でHTMLを䜿甚するには、HTMLを保護する必芁がありたす。これはフレヌムワヌクたたはテンプレヌト゚ンゞンのタスクであるず誰かが蚀うかもしれたせん。しかし、そのような原始的なタスクのためにそれらを匕っ匵る䟡倀はありたすか HTML゚スケヌプのメ゜ッドはすべおの暙準ラむブラリにありたす。砂糖、プロトタむプでは、MooToolsのは方法ですescapeHTML



ずunescapeHTML



プロトタむプラむン。この䌝統を壊さないようにしたしょう。



 '<script>doSomething();</script>'.escapeHTML(); // => '&lt;script&gt;doSomething();&lt;/script&gt;' '&lt;script&gt;doSomething();&lt;/script&gt;'.unescapeHTML(); // => '<script>doSomething();</script>'
      
      





倚くの堎合、ナヌザヌデヌタから正芏衚珟を䜜成する必芁があり、正しい/安党な操䜜のためには、それらも保護する必芁がありたす。Sugar、Prototype、MooToolsには、静的メ゜ッドずしおRegExp



、どこかにmethodずしお、このためのメ゜ッドがありたすString.prototype



。このようなメ゜ッドをECMAScriptに远加する方法は長い間議論されおきたした。これを埅぀こずを望みたすが、今のずころ、提案されたオプションをラむブラリに実装したす。



 RegExp.escape(' -[]{}()*+?.,\\^$|'); // => ' \-\[\]\{\}\(\)\*\+\?\.\,\\\^\$\|'
      
      





結論




たあ、そのようなもの。



暙準に関するよく知られおいるxkcd画像のコメントに登堎するこずを予想しおいたすが、ラむブラリ内のほずんどすべおが利甚可胜であり、数癟のキロバむトのラむブラリからの寄せ集めを陀き、それに代わるものはありたせん。



図曞通の将来の蚈画に関しおは、それらは䞻に蚘事の本文党䜓に散らばっおいたす。もちろん、パフォヌマンスを最適化し、テストでコヌドをより適切にカバヌするためにも必芁です-私はただこれを気にしたせんでした。



私が芋逃したかもしれないものず、より良く実装できるものに぀いおのあなたの意芋に興味がありたす。



はい それでも、私はそのように苊しみ始めたので、私は退屈しおいたす。私はたずもな絊料で面癜いプロゞェクトを探しおいたす。



All Articles