JavascriptOOP、プロトタむプ、クロヌゞャヌ、「クラス」Timer.js

こんにちはプログラマヌ、初心者、卒業生、そしおすべおのシンパサむザヌ。 ご存知のように、個人的な経隓だけでなく、䜕も知られおいない。 䞻なものは、経隓が有甚であるこずです。 そしお、この単玔な考えに続いお、いく぀かの䟿利なこずを䞀床に行うこずを提案したいず思いたす。



譊告 あなたが蚘事から楜しいものを期埅しおいない堎合...あなたは間違っおいたす。 ナヌモアのセンスが䜎い人は読む...さらにお勧め さあ、始めたしょう...



執筆時点ではhello apocalyptic-glamorous 2012javascriptには実際のOOPはありたせんが、オブゞェクト指向プログラミングの基本原則を実装するためのトリックがありたす。 この非垞に興味深いトピックを発芋したばかりの人のために、この方法の特異性を自分の蚀葉で説明したす。



パヌト1。人間の顔をしたOOP。



簡単に説明するず、OOPはたったく神聖なマントラではありたせんが、本質的には、アプリケヌションの線成、コヌドの構造化、メ゜ッドの集䞭化、および゚ンティティを単䞀の階局ファミリに結合するための単なるテクニックです。 朜氎艊ず航空機の建造方法ず同様に、野生生物の浮力ず揮発性の経隓を取り入れお、OOPアプリケヌションはプログラム゚ンティティの認識を「生きおいる」オブゞェクトずしお䜿甚し、実際のオフラむン-芚えおいたすか䞖界から私たちに知られおいる特性ず特性を採甚したす。



぀たり、独自のプロパティずメ゜ッドを持぀だけでなく、子孫を生成しお進化させるこずができる゚ンティティが䜜成されたす これは、拡匵機胜ず呌ばれたす。 泚意深い芪のように、オブゞェクトは継承によっおプロパティを転送するか、別の芪゚ンティティである芪の子孫である䞖代の経隓を受け取りたす。 したがっお、単䞀の生成ツリヌが䜜成されたす。このツリヌでは、手続き型の方法である異皮ラむブラリずは異なり、ナビゲヌトおよび倧量管理が䟿利です。



ご芧のずおり、すべおが人々のようです 開発者はこのシステムの神であり、䜕䞖代にもわたっお継承され、ルヌト自䜓たたは開発の個々のブランチに倉曎を加えるこずができるずいう違いがありたす。 戊争ず玛争を排陀したす 新しい知識-远加 たたはその逆、私たちはすべおを壊したす...神になるのは難しいです ただし、OOPの原則自䜓は、開発者がせっかちではなくルヌルに埓っおアプリケヌションを構築するこずを矩務付けおいるため、サポヌトを容易にし、䜓系化したすが、この堎合でもコヌドを混乱させたいずいう欲求をたったく劚げたせん... :)



私の意芋では、OOPの開発を支揎するのは、たさにそのような「人間」の原則の認識です。 䟋えば、人生のように、子どもたちが自分自身が必芁だず思うこずをできるようにする厳栌な芪がいたす これらは抜象クラス-抜象ず呌ばれたす。 䞡芪がピアノを匟いたり詩を孊ばせたりしたこずを芚えおいたすか..だから、倚くの䞡芪ず同様に、抜象クラスは子孫がなぜそれを必芁ずするのか、そしお圌がそれをどのように䜿甚するのかを知りたせんが、圌らは確信しおいたす必芁です ぀たり このようなクラスには抜象メ゜ッドが含たれたす。抜象メ゜ッドは、キャンディヌのないキャンディヌラッパヌのように、実装自䜓のないメ゜ッドの宣蚀です。これにより、子孫はこのメ゜ッドを実装する必芁がありたす。 人生のように、䞡芪はしばしば満たされおいない倢を子䟛たちに移したす...



このような冗談たじめな圢で、抜象クラスず家族関係のトピックに觊れたした...これらの䞡方を理解する方法ずしお....しかし、真剣に、もちろん、プログラミングにはランダムなメ゜ッドがなく、メ゜ッドずプロパティはよく考え抜かれたクラスの階局。家系図のように、䞖代から䞖代ぞ機胜を拡匵する機䌚を提䟛できたす。 そしお、抜象クラス、さらには抜象クラス-むンタヌフェヌスむンタヌフェヌスには実装がたったく含たれおいないは、プログラマヌが倱うこずのないようにし、人生のすべおの子孫に必芁な共通スキルを実装するこずを忘れないようにしたす。



ゞョヌクに加えお、実際には、たずえば店内の商品などのアプリケヌション芁玠を蚭蚈するずき、オブゞェクト衚珟により、実際のオブゞェクトのプロパティに近づけるこずができたす。これは、人生のように、すべおの必芁な属性をカプセル化したす぀たり、それ自䜓に含たれたす䟡栌、数量、重量、賞味期限およびその他の必芁な品質。 ただし、商品は異なる可胜性があるため、クラスモデルは共通のプロパティを分岐および開発、継承、たたは再定矩できたす。



継承はおそらくOOPの最も重芁な機胜です。 新しいラりンドの進化が必芁な堎合、プログラマヌは芪のスキルを拡匵する新しいクラスを䜜成し、時には新しい方法で実装したす。 重耇する芪メ゜ッド-オヌバヌラむド。 結局のずころ、各䞖代には人生に独自の抂念がありたす...プログラマが前䞖代の「経隓ず抂念」を必芁ずする堎合、圌はそれらに目を向けたす。 この構造では䜕も倱われないため、䜿甚できるこずが非垞に重芁です。



たた、javascriptの完党なOOP仕様はただありたせんが、OOPの原則に埓う機䌚があり、この䟿利さを䜿甚したす。 もちろん、この蚘事の枠組みの䞭で、理解の基本だけに觊れたすが、ご存知のように-面倒なトラブルが始たったので、䞻なこずは理解するこずです...



したがっお、私たちの目暙は、タむマヌによっお必芁なプロセスを開始する䜕らかの制埡された゚ンティティを䜜成するこずです。 「マネヌゞド」-これは、そのような゚ンティティ、たたは条件付きでクラスに含たれるこずを意味したす-カプセル化、コントロヌルのメ゜ッド、および必芁なデヌタを含むプロパティ。 人生の䟋

•プロパティ-これはオブゞェクトが知っおいるものです名前、目の色、乗算衚、

•メ゜ッド-これはオブゞェクトができるこずですスリヌプ、食べ、シンクロファ゜トロンを構築したす。



重芁 読者がオブゞェクトのjavascriptの内容をただ知らない堎合は、事前に参考文献でそれに぀いお読むこずをお勧めしたす。そうしないず、理解が困難になりたす。

オブゞェクトの䜜成は、新しいディレクティブで呌び出される関数を通じお行われたす。 この関数がたったく普通のものではなく、特定のオブゞェクトを䜜成しお返す特別な関数-コンストラクタヌであるず刀断するのは、新しいディレクティブです。 圌女がそれを返す前に、私たちはこのオブゞェクトに、魂が望むすべおのもの、぀たり知識ずスキルの䞡方を割り圓おるこずができたす。



function Timer() { /*    
 */ }; var timer = new Timer();
      
      







そこで、Timerクラスのタむマヌオブゞェクトを䜜成したした。 しかし、創造的な人々ずしお、私たちはすでにオブゞェクトを䜜成する際にいく぀かのプロパティを䞎えたい、たたは䞎えたくないかもしれたせん...それは 必芁に応じお「知識ずスキル」を尋ねるこずができるように普遍性が必芁ですが、䟋えば、呌吞するこずができなくおも、オブゞェクトは苊痛で死ぬこずはありたせん...私たちは動物ではありたせんが、それを行う方法は

これを行うために、クラスに最初に入れるこずは、オブゞェクトが本来受け入れるデフォルトのプロパティです。 そしお凊理ナニット。



 function Timer( options ) { //public var defaultOptions = { delay: 20 //     ,   -   ,stopFrame: 0 //   ,loop: true //    ,frameElementPrefixId: 'timer_' //   ID ,  -  } for(var option in defaultOptions) this[option] = options && options[option]!==undefined ? options[option] : defaultOptions[option]; /*   
 */ };
      
      







たた、関数シグネチャには、optionsパラメヌタヌがありたす。これはオブゞェクトです。 オブゞェクトが䜕であるか知っおいたすか..コメントの埌

//public





生掻に必芁なプロパティを含むdefaultOptionsオブゞェクトもありたす。その背埌には、すべおのdefaultOptionsプロパティを名前で゜ヌトし、オプションを通過するかどうかを確認し、そうでない堎合はdefaultOptionsから倀を蚭定するコヌドブロックです。

オブゞェクトに倀を割り圓おるには、これを䜿甚したす。これは、関数内で䜜成された珟圚のコンストラクタヌを指したす新しいこずを芚えおいたすか。 したがっお、次のようにオブゞェクトを䜜成できたす。



 var timer = new Timer( {delay: 500, loop: false } );
      
      







...指定されたプロパティが曞き蟌たれ、欠萜しおいるプロパティはdefaultOptionsから取埗されたす。 オブゞェクトが保存されたした 汎甚性ず柔軟性が埗られたした



コメントに泚意しおください//public





もちろん、ここには条件倀がありたすクラスの抂念を含むjavascriptのすべおのOOP芏則ず同様が、その本質はパブリックプロパティのマヌクにありたす。 倖郚から入手できたす。 これらのプロパティには、オブゞェクトから盎接アクセスできたす。

 alert( timer.delay );
      
      







人生の䟋ずしお、これらは隠される必芁のないオブゞェクトの明らかな特性、぀たり猫の尻尟の長さです。



たた、個人のプロパティ-プラむベヌト、および保護-保護されおいたす。 Personalにアクセスするには、蚱容される堎合は、プログラマが䜕をどのように、誰に返品できるかを決定する特別な方法を䜿甚する必芁がありたす。 保護されおいる-保護されおいる、それは少し個人的ではない、なぜなら いわゆる「家族」の茪の䞭で、クラス自䜓ずその盞続人の䞡方がアクセスできたす。 これは、アプリケヌションの安定性のために行われたす。すべおのゎミが小屋に耐える方が良いずいうわけではないためです...



パヌ゜ナルプロパティを远加したしょう-プラむベヌト、これは関数内に内郚倉数を䜜成するこずで行われるため、そのスコヌプは関数自䜓によっお制限されたすたたは閉じられたす。 クロヌゞャに぀いお説明したす...䞀方、Timer関数にさらに挿入したす。



  //private var busy = false, //  ""  " !" currentTime = 0 //   ,frame = 1 //   ,task = {} // ! !         ,   ,keyFrames=[] //    , ..      ; /*   
 */
      
      





そのようなプロパティに、必芁に応じお、次のようなパブリックメ゜ッドを介したアクセスを蚱可したす。

 this.getKeyFrames = function( ) { return keyFrames; }
      
      





このメ゜ッドはパブリックであるこずに泚意しおください。 これにより、オブゞェクトのプロパティに割り圓おられ、ポむントを介しおアクセスできたすアクションを呌び出す堎合は、最埌の角かっこを忘れないでください。



 timer.getKeyFrames();
      
      







プラむベヌトメ゜ッドが必芁な堎合、プラむベヌト倉数ず同様に、内郚関数の「通垞の」宣蚀によっおも䜜成されたす。



 function somePrivateMethod() { /* some code... */ }
      
      







デザむナヌが個人的な目的で呌び出すこずができるサヌビス機胜が刀明したした。 ただし、コンストラクタヌによっお䜜成されたオブゞェクトからは、この関数は䜿甚できたせん。 圌の財産ではありたせん。



繰り返したすが、javascriptでは、これらはすべお、OOPの原則に埓うのに圹立぀芏則ですが、垞に正確な実装を提䟛するずは限りたせん。 たずえば、javascriptでのprotectedの実装は非垞にタむトです 実際、protectedは郚分的に、オブゞェクトからのアクセス䞍胜のためのprivateプロパティず、他のクラスからのアクセスのためのpublicの䞡方のプロパティを結合したす。 たたは、パブリックメ゜ッドを䜜成し、そのメ゜ッドを呌び出すオブゞェクトがメ゜ッド所有者の盞続人であるかどうかなどを内郚で確認できたす。 慣習の枠組みの䞭で、理想的な解決策はありたせん。



さお、アクセス組織を少し敎理したした。 これはOOPで最も重芁な品質、぀たり䞡芪のスキルず知識を採甚し、開発する胜力であるため、継承に぀いおはどうですか そしおここで、javascriptの重芁な機胜であるプロトタむプの継承に぀いお説明したす。 このトピックは理解するのにしばしば困難を匕き起こしたす、そしお、私は単玔な人間の蚀語で「すべおをきっぱり説明する」私の詊みをしたす。



パヌト2. JavaScriptのプロトタむプ。



そのため、javascriptにはプロトタむプの抂念、オブゞェクトの隠しリンク[[prototype]]、__ proto__、および関数のプロトタむププロパティがありたす。 これらの抂念の混乱を避けるために、それらを1぀ず぀分析したす。







自尊心のあるjavascriptオブゞェクトには隠しリンク[[prototype]]があり、芪オブゞェクトに関連付けられ、芪オブゞェクトに関連付けられたす。 このチェヌンの最䞊郚には、組み蟌みjavascriptオブゞェクト、䞀皮の最高の前駆䜓、toString、valueOf、hasOwnPropertyなどの必芁なすべおの組み蟌みメ゜ッドを備えたオブゞェクトアダムがありたす。 このため、すべおの子孫オブゞェクトには、最䜎限必芁な䞀連のメ゜ッドがあり、難しいjavascript環境で生き残るこずができたす。



thread_object2-[[プロトタむプ]]-> thread_object1-[[プロトタむプ]]-> ... {toString...、valueOf...、hasOwnProperty...、...}



぀たり メ゜ッドずプロパティを持たない空のvar obj = {}オブゞェクトを䜜成し、暙準メ゜ッドに切り替え、[[prototype]]リンクチェヌンこの堎合、最小の短いチェヌンを䜿甚しお、組み蟌みjavascriptオブゞェクトからこのメ゜ッドを取埗したす。



 var obj = {}; //  obj.toString(); //      "[object Object]"
      
      







これは、リンクのチェヌン[[prototype]]を介しお、javascriptでプロトタむプ継承が実装される方法です。 プロトタむプチェヌンを通じお利甚できるすべおのプロパティは、知識ずスキルの倉庫のように子孫に開かれ、実際に進化するクラスのツリヌを構築できたす



各オブゞェクトのプロトタむププロパティはその䞭に保存されるのではなく、珟圚のオブゞェクトず組み蟌みのjavascriptオブゞェクトの間のプロトタむプチェヌンの䞭間リンクに「時間の初めに」保存されるこずに泚意しおください。 このルヌトオブゞェクトには敬意が必芁であり、その平和を乱すこずはきちんずしたものではありたせん。したがっお、独自のプロトタむププロパティを䜜成するには、リンク[[prototype]]を䜿甚しお独自のオブゞェクトを䜜成しおチェヌンに埋め蟌む方が良いでしょう



しかし、芚えおいるように、[[prototype]]は閉じたリンクです。どうすればアクセスできずにチェヌンを構築できたすか ここでは、新しいキヌワヌドを備えた既によく知られおいるConstructor関数ず、それ自䜓に察しお非垞にオヌプンなprototypeプロパティが圹立ちたす。 実際、コンストラクタヌを介しお䜜成されたオブゞェクトは、このコンストラクタヌのprototypeプロパティで指定された倀を持぀[[prototype]]リンクを取埗したす 最初、すべおの関数のプロトタむププロパティには、ほずんど空のオブゞェクトぞの参照がありたす関数自䜓を指す単䞀のコンストラクタヌプロパティ。



function_protection.prototype-> {コンストラクタ-> function_profection}



しかし、芪クラスを枡すこずにより、プロトタむププロパティを眮き換えるこずができたす。 ぀たり Constructor関数を䜜成するずき、プロトタむププロパティで必芁なプロパティを持぀オブゞェクトぞの参照を割り圓おるだけで、䜜成する新しいオブゞェクトは、必芁なプロパティを持぀このオブゞェクトぞの[[prototype]]リンクを受け取りたす。



 //   "" var Foo = function() {}; //  prototype      Foo.prototype = { hi: 'Hello!', sayHi: function(){ alert( this.hi ) } }; //   "" var obj = new Foo(); //  ,    obj.sayHi();
      
      







䞊蚘の䟋では、objオブゞェクトの非衚瀺リンク[[prototype]]が、hiプロパティずsayHiメ゜ッドを持぀オブゞェクトぞのポむンタヌを受け取りたした。 したがっお、objオブゞェクトはこの知識ずスキルを継承したす。

この手順を簡玠化するために、関数が考案されたした。



 function extend(Child, Parent) { var F = function() { } F.prototype = Parent.prototype Child.prototype = new F() Child.prototype.constructor = Child Child.superclass = Parent.prototype }
      
      







その䜿甚䟋、javascript.ruを参照

javascript.ru/tutorial/object/inheritance#svoystvo-prototype-i-prototip



匕数には、コンストラクタヌ、子孫、および芪の2぀の関数が必芁で、既に説明したこずを実行したす。





問題が発生する可胜性がありたす。なぜ最初の3行が必芁なのか、新しいFなしで代入をすぐにChild.prototype = Parent.prototypeにしないのか、そしおそれで終わりですか



実際、この割り圓おでは、継承チェヌンの新しい䞭間リンクは䜜成されたせん Parent.prototypeはChild.prototypeに曞き蟌たれ、Parent.prototypeをさらに参照する䞭間ストレヌゞオブゞェクトではありたせん。Child.prototypeに䜕かを曞き蟌もうずするず、芪の領域に倧たかに䟵入し、長老ぞの敬意ず䞖代の継承に違反したす。 新しいFコンストラクタヌを呌び出すこずで、子孫に枡すこずができるプロトタむプの知識を栌玍するための独自の領域をChildに䜜成したす。



次の方法で、Designerのプロトタむプに個々のプロパティを远加できたす。



 Child.prototype.someProperty = "someProperty";
      
      







ずころで、プロトタむプをオブゞェクトのプロパティ、぀たりクラスのむンスタンスずしお参照しようずしないでください。

オブゞェクトにはプロトタむププロパティがありたせん。非衚瀺リンク[[prototype]]がありたすが、プロトタむププロパティにはありたせん。

もちろん䜜成するこずはできたすが、継承する意味はありたせん。 Senseは、䜜成されたオブゞェクトの[[prototype]]リンクにポむンタヌを枡すこずができるため、Constructor関数のprototypeプロパティからのみです。



プロトタむプの継承は以䞊です。 本圓に簡単ですか

ただし、可胜なのはプロトタむプの継承だけではありたせん。 たた、スヌパヌクラスのコンストラクタヌを呌び出す方法、぀たり 芪クラスの堎合、プロトタむププロパティぞの曞き蟌みを凊理したのは䜕の理由でもありたせん関数extendを参照。



忘れられた䟋のTimerコンストラクタヌでは、これを介しおいく぀かのプロパティをオブゞェクトに割り圓おたす。 これらのプロパティを将来の䞖代に枡すには、子孫のコンストラクタヌで芪コンストラクタヌを呌び出す必芁がありたす。぀たり、



 function TimerPlayer() { TimerPlayer.superclass.constructor.apply( this, arguments ); }
      
      







this.superclass.constructor.applyを介しお、぀たり珟圚のコンストラクタヌここではTimerPlayerの名前を介しお呌び出すこずはできないこずに泚意しおください。そうでない堎合、芪コンストラクタヌもこれを䜿甚し、this.superclass.constructor.applythis、匕数、これは子孫ずしおthisのコンテキストに適甚する閉じられた呌び出しに倉わり、゚ラヌが発生したす。



子孫のコンテキストで芪コンストラクタを呌び出すず、すべおのプロパティずメ゜ッドが䜜成され、子孫に割り圓おられたす。 さらに、これを介しおではなくvarを介しお宣蚀された芪のプラむベヌトプロパティは、読み取りを蚱可する芪のパブリックメ゜ッドがある堎合にのみアクセスできたす。

このようにしお、タむマヌを構築し続けたす。



パヌト3. JavascriptクラスTimerずそのレガシヌ。



そのため、すでに䜕かを知っおいるクラスがありたすが、方法はわかりたせん。そのため、スキルを远加するずきが来たした クラスに䜕を教えたいですか プレむダヌのようなものを䜜りたしょう

•開始

•䞀時停止

•停止

•巻き戻し

•setToFrame

そしお、いく぀かのそれほど重芁ではない方法。 すでにそれらを曞いたず想像しおください...それで、Timer関数にさらに挿入したす。



 this.start = function(){ /*  */ if( busy ) return; if( window.console ) console.log ('start: .currentTime='+currentTime+'; frame='+frame); busy = true; timer.call( this ); } this.pause = function() { /*  */ if( window.console ) console.log ('pause: currentTime='+currentTime+'; frame='+frame); clearInterval( this.intervalId ); busy = false; } this.stop = function() { /*  */ if( window.console ) console.log ('stop: currentTime='+currentTime+'; frame='+frame); clearInterval( this.intervalId ); busy = false; currentTime = 0; frame = 1; this.clearFrameLine(); } /* highlighting -   */ this.clearFrameLine = function() { /*    */ for(var i=1, str=''; i<this.stopFrame+1; i++) if( elFr = document.getElementById( this.frameElementPrefixId+i ) ) removeClass( elFr, 'active'); } this.setActiveFrameElement = function( frameNumber ){ /*    */ if( elFr = document.getElementById( this.frameElementPrefixId+frameNumber ) ) addClass(elFr, 'active'); } this.toString = function() { /*  ,   alert(),    */ var str = ''; for(var option in this ) str+= option+': '+( (typeof this[option]=='function') ? 'function' : this[option] )+'\n'; return '{\n'+str+'}'; } this.setTask = function( new_task ) { /*   ,       */ task = new_task; this.stopFrame = 0; keyFrames.length = 0; for(var frInd in task) { if( (+this.stopFrame)< (+frInd) ) this.stopFrame=(+frInd); keyFrames.push( +frInd ); } } this.getKeyFrames = function( ) { /*    keyFrames */ return keyFrames; } this.getTask = function() { /*    task */ return task; } this.setToFrame = function( toFrame ) { /*     */ if(toFrame>this.stopFrame) return; frame=toFrame; currentTime=(frame-1)*this.delay; for(var frInd in task) { if( (+frInd)>(+toFrame) ) break; var taskList = task[ frInd ]; for(var i=0; i<taskList.length; i++ ){ var taskItem; if( taskItem = taskList[i] )taskItem.run(); } } this.clearFrameLine(); this.setActiveFrameElement( toFrame ); } this.rewind = function( amount ) { /* !  !      :))))))))) */ if( amount<0 && this.intervalId ) amount--;/*    setInterval */ var toFrame = frame+amount; toFrame = Math.max( Math.min( toFrame, this.stopFrame), 1); this.setToFrame(toFrame); } function timer(){ /*  ,  setInterval      */ var this_ = this; /*         */ this.intervalId = setInterval( function() { /*    setInterval    this.delay */ //console.log ('currentTime='+currentTime+'; frame='+frame+';'+task); if( task[ frame ] ) { /*       ,  ... */ var taskList = task[ frame ] /* ...   -   */ for(var i=0; i<taskList.length; i++ ){ /*     -    - run... */ var taskItem; if( taskItem = taskList[i] ) taskItem.run(); /* ...     */ } } /* highlighting */ this_.setActiveFrameElement( frame ); /*   */ currentTime+=this_.delay; /*      */ frame++; if( this_.stopFrame && frame>this_.stopFrame ) { /*  stopFrame       ... */ if( this_.loop ) this_.setToFrame( 1 ); /*    - ,    ,   ,  , */ else this_.stop(); /*   ! */ } }, this.delay ); }
      
      







すべおがデザむナヌで終わりたした。

䞀般的に、私はすべおが明確だず思いたすあなたは開始方法が必芁ですか パブリックスタヌトメ゜ッドを䜜成しおいたす どこで...



 this.start = function(){ if( busy ) return; /*    ,  ! */ /*   ,     */ if( window.console ) console.log ('start: .currentTime='+currentTime+'; frame='+frame); busy = true; /*  ,   */ timer.call( this ); /*    */ }
      
      







タむマヌ機胜自䜓に぀いお詳しくコメントしたした。 党䜓のアむデアは簡単です。



 function timer(){ var this_ = this; this.intervalId = setInterval(function() { /*    ,  this_   this! */ }, this.delay ); }
      
      







たず、オブゞェクトのコンテキストぞのリンクを倉数に保存したす。なぜなら、 setIntervalで呌び出された関数内では、コンテキストは倱われ、倉数はクロヌゞャヌ、぀たりロヌカルスコヌプに残りたす。 おそらく理解するために、クロヌゞャヌに぀いお繰り返すたたは調べる必芁があり、埌で説明したす...次に、オブゞェクトにintervalIdプロパティを割り圓おたす。これはsetIntervalメ゜ッドによっお返されたす。この識別子により、䞀時停止たたは停止時にsetIntervalを停止できたす。



タスクプロパティには別の分析が必芁です。これは、䜕らかのフォヌムでタスクを実行するために保存するためです。 その構造は次のずおりです。



 { 1:[ { run: function(){} } ], 5:[ {},{},{} /*...*/ ], /*...*/ }
      
      







オブゞェクトはオブゞェクトの配列です。 ああ、蚀わない方がいいです。さもないず混乱しおしたいたす...

ただし、すべおが単玔です。目的のフレヌム番号の䞋のタスクオブゞェクトには、runプロパティを持぀タスクオブゞェクトの配列が含たれおいたす。 このプロパティには、目的のフレヌムが呌び出されたずきに呌び出される関数を割り圓おる必芁がありたす。 必芁に応じお、各タスクオブゞェクト、別のプロパティを远加しおから、圌ずオブゞェクトを远加できたす。



たた、必芁に応じお、プッシュ、シフト解陀、スプラむス配列の暙準的な方法を䜿甚しお、新しいタスクオブゞェクトを配列に远加できたす。

もちろん、タスクオブゞェクト自䜓には、目的のフレヌムの番号によっおプロパティを割り圓おるこずができたす



したがっお、タスクに入力し、setTaskメ゜ッドを䜿甚しおクラスを割り圓おお、䜕をい぀実行するかを決定したす。 これはどのように䜿甚できたすか サむトたたはオフラむンクラむアントでさたざたな動的シナリオを実行し、アニメヌションを䜜成し、時間に関連する「ラむブ」チュヌトリアルたたはテストを䜜成し、重芁なむベントを思い出させたすやかんが沞隰したす。 たたは、ペヌゞの隅に時蚈を衚瀺するだけです



さらに、タむマヌず芖芚化を制埡するための䞀皮の小さなAPIである最も単玔なむンタヌフェむスを既に敎理しおおり、今ではそれを䜿甚しお、プレヌダヌのようなコントロヌルパネルを構築しおいたす htmlペヌゞにお気に入りのコヌドを挿入したす。



 <button onclick="timer.rewind(-50);">rewind -50</button> <button onclick="timer.start();">start</button> <button onclick="timer.pause();">pause</button> <button onclick="timer.stop();">stop</button> <button onclick="timer.rewind(+50);">rewind +50</button>
      
      







onclickむベントでは、タむマヌオブゞェクトのメ゜ッドでボタンがハングしたす。 もちろん、どのオブゞェクトを呌び出す前に、䜜成するこずを忘れないでください。 芚えおる -コンストラクタヌ関数を䜿甚

 var timer = new Timer();
      
      







しかし、今ではスクリプトを䜜成するこず、それを管理する方法、それ以倖の堎合、䜕のために戊っおいたのは悪くないでしょう。

単玔なアニメヌションを䜜成しおみたしょう。ペヌゞの呚りで画像を移動したす。たあ、アニメヌションの䞖界の䞀皮の「ハロヌ䞖界」です。 写真を移動したす

 <img id="ball" src="http://www.smayli.ru/data/smiles/transporta-854.gif" >
      
      









タむマヌのタスクは、私たちが奜きなアクションをトリガヌするこずですが、圌自身はこのアクションに責任を負いたせん。 したがっお、正確に䜕をすべきかがタスクであり、IDずその2぀の座暙によっお芁玠自䜓を転送する芁玠を移動するための単玔な関数を蚘述するこずで、これを解決したす。



 function moveElem( elem, top, left ){ elem.style.cssText = 'position:relative;top:'+top+'px;left:'+left+'px'; }
      
      







だから、今、この関数はタスクオブゞェクトの必芁なフレヌムの数の䞋の配列でタスクオブゞェクトの実行プロパティに割り圓おる必芁がありたす、考えに泚意しおくださいそこで、スクリプトオブゞェクトを䜜成し、その最初のフレヌムを配列ずしお定矩したす。このフレヌムには、ピクチャ゚レメントの初期䜍眮を配眮したす。



 var frames = {}; /*   */ frames[1]=[]; frames[1].push( { run: function(){ moveElem( ball, 600, 600 ); } } );
      
      







runmoveElemball、600、600を曞けないのはなぜですか構文が...

moveElem;であるため、これは間違っおいたす。

...は関数呌び出しを意味したすが、ここで呌び出す必芁はありたせんが、本䜓にrun関数プロパティを配眮する必芁がありたす。これにより呌び出しが行われたす。さもなければ、moveElemの結果を実行したす-䜕も返さないため、未定矩で、なぜ画像を無駄にしたのでしょうか



そしお出来䞊がり最初のフレヌムに、ペヌゞの特定の䜎い䜍眮に画像バルヌンを配眮するアクションを远加したした。さお、䞊昇を開始するには、この状態をフレヌムごずに倉曎する必芁がありたす。座暙を䞊、䞋、巊に枛らしたす-颚に合わせお調敎したす。:)必芁なフレヌムを埋めるには、ルヌプを䜿甚したす。必芁に応じお、タむマヌクラスの独自のメ゜ッドを蚘述するこずができたす-フレヌムずアクションを远加し、アクションの倉曎パラメヌタヌをフレヌムごずに分散したす...䞀方、たずえば、2番目から600番目のサむクルたでフレヌムを埋めたす。



 /*  */ for(var i=2; i<601; i++) frames[i] = [ { run: function(i){ return function(){ moveElem( ball, 600-i, 600-i ); } }(i) } ];
      
      





ここでは、クロヌゞャヌの䜿甚にも泚意を払う必芁がありたす。実際には、動的iを転送するために、ここでは適切な堎所で呌び出される関数匏でラッピングを䜿甚しおいたす。



 function(i){ /*    i    */ }(i) ;
      
      







䜿甚したばかりの堎合



 run: function(){ moveElem( ball, 600-i, 600-i ); }
      
      







次に、moveElemを呌び出すず、グロヌバルスコヌプから取埗されたす。forルヌプで宣蚀しお実行したものvar i = 2; i <601; i ++、぀たり 「ワヌクアりト」倉数iは600になりたすが、ダむナミックiは呌び出されたせん。ダむナミックiは埐々に増加し、離陞ボヌルの座暙を倉曎したす。

したがっお、JavaScriptでCLOSEを䜿甚したす。これは、スコヌプを定矩したす。機胜を実行するずき



 function(i){ /*    i    */ }(i) ;
      
      







...その内郚では、独自の倉数iがこの関数自䜓の匕数ずしお䜜成され、その堎での呌び出し忘れた堎合は繰り返しが関数の本䜓を実行し、関数が戻りたす。そしおたた

じゃない



 return moveElem( ball, 600-i, 600-i );
      
      







でも



 return function(){ moveElem( ball, 600-i, 600-i ); }
      
      







前者の堎合、関数呌び出しは返されたせんが、すぐに実行されるmoveElemball、600-i、600-iの呌び出しの結果が返されるためです



そしお今、スクリプトがありたす。これで、割り圓おお実行できたす。



 var timer = new Timer( ); timer.setTask( frames ); timer.start(); /*   start */
      
      







䞀般に、フレヌムごずの制埡は、興味深い耇雑なシナリオを䜜成するための広範な可胜性を提䟛したす。denis-or-love.narod.ru/portf/timer

デモペヌゞで、 Adobe FlashのTimeLineのようなタむムラプスラむンの䟋を実装したした:)-drawFrameLineボタン。



ペヌゞ䞊の芁玠の数が倚いず、䜍眮を再描画するずきにブラりザの速床が倧幅に䜎䞋する可胜性があるこずに泚意しおください。

必芁に応じお、拡匵可胜な機胜やその他の機胜を備えたスクリプト䜜成甚のむンタヌフェむス党䜓を䜜成できたす。ここで、圌らが蚀うように、誰がそんなに



画像



倧事なのか... そしお今、遺産に行こう

ベヌスのTimerクラスを䜜成したら、より高床なTimerPlayerクラスを䜜成しお、それを拡匵したす。進歩の䟋を単玔な䟋に制限したしょう。芪のスキルを取り入れた子クラスは、タむマヌのようなコントロヌルパネルをプレヌダヌのように䜜成できたす。これを行うには、次の3぀のこずを行いたす。

  1. 芪コンストラクタヌを呌び出す
  2. 新しいメ゜ッドを远加する
  3. 拡匵機胜を介しお継承を枡す




 //  function TimerPlayer( options ) { //    TimerPlayer.superclass.constructor.apply(this, arguments); //   this.drawPanel = function( panelId, objName ) { var objName = objName || 'timer'; var template ='<button onclick="'+objName+'.rewind(-50);">rewind -50</button>'+ '<button onclick="'+objName+'.start();">start</button>'+ '<button onclick="'+objName+'.pause();">pause</button>'+ '<button onclick="'+objName+'.stop();">stop</button>'+ '<button onclick="'+objName+'.rewind(+50);">rewind +50</button>'; document.getElementById( panelId ).innerHTML = template; } } // extend extend(TimerPlayer, Timer);
      
      







ここにはプロトタむプの継承はありたせんが、将来のためにチェヌンを構築し芪にプロトタむプのプロパティを远加したい堎合は...、スヌパヌクラスずコンストラクタヌを蚘述するために拡匵する必芁がありたす。新しいdrawPanelメ゜ッドは、ボタンを配眮する芁玠のid文字列を受け入れたす。文字列は、HTMLテンプレヌトに眮換されるオブゞェクトの名前です。



 //   var timerPlayer = new TimerPlayer(); timerPlayer.setTask( frames2 ); timerPlayer.drawPanel( 'controlPanel', 'timerPlayer' );
      
      







終了したか、Timerクラスずその子孫を開始しただけです。この蚘事を曞くにあたっお、患者のアドバむスず支揎に専念しお

いただきたいず思いたす。再䌚しおプログラミングを楜しむたで。




All Articles