Quantcast
Channel: 初心者タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 21085

写経のすヽめ

$
0
0

創作は真似事から始まる

わりとよく聞く言葉だとは思いますが、世の中に存在する全ての作られたものは模倣から始まっていると思います。完全オリジナルなんてないのです。多分。
幼年期に絵を書いていた人は恐らくドラえもんやアンパンマンの落書きから始まって、そこから色んな絵を描き、成長と共に色んなアレンジや技法を知り、自分のものにしたり。
小さい頃ピアノを習ってた人だって、いきなりオリジナル曲を作れる人は稀有なんではないでしょうか。恐らく。

Let's 写経

例えばjavascriptを学習するとき、分厚い教本を買って小難しいカタカナなどを乗り越えながら手を動かしつつ学習する人もいると思うのですが(私がそうです)、個人的には自分に向いてないと思いました。

まず構文がわからん。
「え、なにこの書き方?」
みたいなのを見つけても説明がなかったりします。
ネットで調べようにも調べ方がわからなかったり。

知識を吸収しようにも教本だけではもどかしく、「え、なにこれ」が発生した場合解決するまで次のステップへ進めない(それができる人もいるのでしょうけども)。

というわけで、私みたいにじゃあ教本に頼りっぱなしではなく自分でコードを書きまくって覚えちまおうって人に向けたい話が今回伝えたいことです。Let's 写経。

どうするの?

GitHubでもなんでもいいので、オープンソースのコードを拾ってきます。
難易度はばらつきがあると思いますが、自分ならこれを解読しながら模写できそうと思えるのがいいかも。
思えるものがなかったらとりあえず片っ端からやっていきましょう。

例えば

varutils={wrap:function(el,className){if(!el){return;}varwrapper=document.createElement('div');wrapper.className=className;el.parentNode.insertBefore(wrapper,el);el.parentNode.removeChild(el);wrapper.appendChild(el);},addClass:function(el,className){if(!el){return;}if(el.classList){el.classList.add(className);}else{el.className+=''+className;}},removeClass:function(el,className){if(!el){return;}if(el.classList){el.classList.remove(className);}else{el.className=el.className.replace(newRegExp('(^|\\b)'+className.split('').join('|')+'(\\b|$)','gi'),'');}},hasClass:function(el,className){if(el.classList){returnel.classList.contains(className);}else{returnnewRegExp('(^| )'+className+'( |$)','gi').test(el.className);}returnfalse;},// ex Transform// ex TransitionTimingFunctionsetVendor:function(el,property,value){if(!el){return;}el.style[property.charAt(0).toLowerCase()+property.slice(1)]=value;el.style['webkit'+property]=value;el.style['moz'+property]=value;el.style['ms'+property]=value;el.style['o'+property]=value;},trigger:function(el,event,detail=null){if(!el){return;}letcustomEvent=newCustomEvent(event,{detail:detail});el.dispatchEvent(customEvent);},Listener:{uid:0},on:function(el,events,fn){if(!el){return;}events.split('').forEach(event=>{var_id=el.getAttribute('lg-event-uid')||'';utils.Listener.uid++;_id+='&'+utils.Listener.uid;el.setAttribute('lg-event-uid',_id);utils.Listener[event+utils.Listener.uid]=fn;el.addEventListener(event.split('.')[0],fn,false);});},off:function(el,event){if(!el){return;}var_id=el.getAttribute('lg-event-uid');if(_id){_id=_id.split('&');for(vari=0;i<_id.length;i++){if(_id[i]){var_event=event+_id[i];if(_event.substring(0,1)==='.'){for(varkeyinutils.Listener){if(utils.Listener.hasOwnProperty(key)){if(key.split('.').indexOf(_event.split('.')[1])>-1){el.removeEventListener(key.split('.')[0],utils.Listener[key]);el.setAttribute('lg-event-uid',el.getAttribute('lg-event-uid').replace('&'+_id[i],''));deleteutils.Listener[key];}}}}else{el.removeEventListener(_event.split('.')[0],utils.Listener[_event]);el.setAttribute('lg-event-uid',el.getAttribute('lg-event-uid').replace('&'+_id[i],''));deleteutils.Listener[_event];}}}}},};

↑こういうコードを

varutils={//utilsオブジェクト作成wrap:function(el,className){//wrap作成if(!el){//elがtrueでなかった場合return;//undefinedを返す}varwrapper=document.createElement('div');//divタグを生成wrapper.className=className;//生成されたdivタグのclassNameが引数のclassNameとなるel.parentNode.insertBefore(wrapper,el);//wrapper(div)をelの前に挿入el.parentNOde.removeChild(el);//elを削除wrapper.appendChild(el);//wrapperの子要素としてelを追加},addClass:function(el,className){//class追加if(!el){//elがtrueでなかった場合return;//undefinedを返す}if(el.classList){// el.classListがtrueならばel.classList.add(className);//elのclassにclassNameを追加}else{el.className+=''+className;//それ以外は「"elのクラス名"&nbsp;className」という文字列を生成}},removeClass:function(el,className){//class削除if(!el){//elがtrueでなかった場合return;//undefinedを返す}if(el.classList){//el.classListがtrueならばel.classList.remove(className);//elのclassからclassNameを削除}else{//それ以外のときはマッチする全てのクラス名を空白にel.className=el.className.replace(newRegExp('(^|\\b)'+className.split('').join('|')+'(\\b|$)','gi'),'');//それ以外のときはマッチする全てのクラス名を空白に}},hasClass:function(el,className){//class判定if(el.classList){//el.classListがtrueならばreturnel.classList.contains(className);//classListの中身をマッチさせた結果を返す}else{//それ以外の時はclassNameをマッチさせた結果を返すreturnnewRegExp('(^| )'+className+'( |$)','gi').test(el.className);}returnfalse;//falseを返す},// 動きを与える// transitionでのタイミング操作の関数setVendor:function(el,property,value){//ベンダープレフィックス付与if(!el){//elがtrueでなかった場合return;//undefinedを返す}el.style[property.charAt(0).toLowerCase()+property.slice(1)]=value;//頭文字が大文字のものを小文字にel.style['webkit'+property]=value;//webkit付与el.style['moz'+property]=value;//moz付与el.style['ms'+property]=value;//ms付与el.style['o'+property]=value;//o付与},trigger:function(el,event,detail=null){//event発火if(!el){return;}letcustomEvent=newCustomEvent(event,{detail:detail});el.dispatchEvent(customEvent);//CustomEventを発生させる},Listener:{uid:0},on:function(el,events,fn){if(!el){return;}events.split('').forEach(event=>{//eventsを配列に置換し、foreachで繰り返し処理var_id=el.getAttribure('lg-event-uid')||'';//elの属性にlg-event-uidが含まれていれば_idに代入、それ以外は空の値を代入utils.Listenr.uid++;//uidに1を追加していく_id+=utils.Listener.uid;// _idにuidを追加していくel.setAttribute('lg-event-uid',_id);// elのlg-event-uid属性に_idの値を付与utils.Listener[event+utils.Listener.uid]=fn;//utils.Listenerオブジェクトにevent+uidの数値というプロパティを追加し、値をfnにするel.addEventListener(event.split('.')[0],fn,false);//eventsの1番目のイベントがハンドラとなり、fnを実行。そのイベントは伝播する。});},off:function(el,event){if(!el){return;}var_id=el.getAttribure('lg-event-uid');if(_id){//_idがtureだったら_id=_id.split('&');//_idを&単位で分割し配列にするfor(vari=0;i<_id.length;i++){//_idの個数分だけiの数値を増加if(_id[i]){//_id配列がtrueだったらvar_event=event+_id[i];//_eventにeventと_id配列の数値を足したものを代入if(_event.substring(0,1)==='.'){//_event文字列の頭文字が.だったらfor(varkeyinutils.Listener){//utils.Listenerの値を反復if(utils.Listener.hasOwnProperty(key)){//Listenerがkeyをもっていればif(key.split('.').indexOf(_event.split('.')[1])>-1){//keyを.で分割した配列の中に、_eventを.で分割した配列の2番目の値が一致したものが-1よりel.removeEventListener(key.split('.')[0],utils.Listener[key]);//keyを.で分割した配列の最初の値のイベントで、utils.Listenerのプロパティを削除していくel.setAttribute('lg-event-uid',el.getAttribure('lg-event-uid').replace('&'+_id[i],''));//elのlg-event-uid属性にlg-event-uidの&とidを削除した文字列の値をセットdeleteutils.Listener[key];//utilsのListennerの中のkeyプロパティを削除}}}}else{//_id配列がfalseだったらel.removeEventListener(_event.split('.')[0],utils.Listener[_event]);//eventsの1番目のイベントがハンドラとなり、utils.Listener[_event]を削除。el.setAttribute('lg-event-uid',el.getAttribute('lg-event-uid').replace('&'+_id[i],''));//elのlg-event-uid属性にlg-event-uidの&とidを削除した文字列の値をセットdeleteutils.Listener[_event];//utilsのListennerの中の_eventプロパティを削除}}}}}};

↑こう書いていきます。
もちろんコピペはNGで、元のソースを見ながら全て手書きで書いていきます。

スクリーンショット 2019-11-30 14.17.07.png

エディター上で両ソースを見れる状態にしておき、オリジナルを見ながら模写していくってのがやりやすいかもしれないです。

結局写経したらどうなるの?

例えば見慣れない構文を見つけたとき、
この書き方はどういう機能を意味してるのか?
この処理はなにを意味しているのか?
そもそもこの記号何?
とか色々疑問が湧いてきます。
自分の手で書き写して、見慣れない構文はその都度調べて、既にある機能を自分の手で作り上げて行くのです。関数の書き方、効率的な処理の書き方、よくわからない記号の意味がじわじわわかったりしてきます。

楽器で例えるなら、ギターの練習の際基礎練はほどほどに既成曲ばっかり弾きまくって上達していくといった感じでしょうか。当然基礎は大事ですが、人によってはガシガシ手を動かした方が吸収できる人もいるようです。自分にあった学習の仕方があるとは思いますが、教本は補助教材としてわからないことがあったときに確認するようにして、あとはひたすら書く、というのが性に合ってる人はハマると思います。


Viewing all articles
Browse latest Browse all 21085

Trending Articles