【CSS】疑似クラス :target の使用方法
cssの疑似クラスって結構あるんですよね。
動作といったらjQueryとかで記述しちゃいがちなのですが、cssだけでも様々な動作が作れます。
cssで済んだほうが楽だし軽量なので、できる限りcssだけで済ませたいものです。
忘れないように、動作を作成する際有用な:target疑似クラスについて今回はメモしていきます。
以下で、要素の移動とモーダルウィンドウをcssのみで作成してみました。
HTMLとSCSSのタブを切り替えてコードを見てみてください。
See the Pen target css by nao (@kumapoyo) on CodePen.
動作をつけたい要素にHTMLでidを指定し、cssで:targetを付けます。
動作をつけたい要素へのアンカーリンクをクリックした際に発火します。
:not疑似クラスを使用し、:targetではない場合にもtransitionでスムーズに戻るようにしています。
【JavaScript】とてもややこしいスコープチェーン
スコープチェーンについてメモします。
スコープチェーンの検索は、このように最初に発見した値を返します。
xの中身が上書きされていくということは大体想像が付きます。
処理を括るクロージャーの考えを踏まえると、
関数の外でxを呼んだ場合グローバルでxに代入したfalseが出力されます。
ここまではそんなにややこしいことはないのですが、
次の例からややこしくなっていきます。
ややこしや~
上から順に、まずグローバルで変数aに1を代入していますね。
次に変数funcにaをコンソール出力させる関数を代入してます。
次に即時関数内で、変数aに今度は100を代入させます。
※ (); ←これは関数を即時に実行させます。
次にfを実行していますが、fは引数で、
最後の行で引数に二行目で定義したfunc関数を渡しています。
ということで、即時関数内でfunc関数を実行しているわけですが、 先ほどのようにスコープチェーンの検索の仕方と、クロージャーの考えを踏まえると
同じ関数内で変数aに100を上書きしているため、コンソールで出力されるのは100じゃないかなと思います。(私はそう思いました)
ですが、ログで出力されるのはなんとグローバルで代入した1を出力するのです。
これはスコープは関数実行時ではなく、定義時に決められる為なのです。
二行目の
var func = function() { console.log(a); };
ここで定義した時点で、aはスコープチェーンの検索で一行目のvar a = 1;を見ているのです。
なので、この関数を呼び出した関数内のaはスルーされたのでした。
スコープは関数実行時ではなく、定義時に決められる
これが分かってないと出くわした際に躓いてしまいそうですね。
【JavaScript】thisを変数に代入する理由
JavaScriptの基本編。
thisが思いもよらない動作をすることがあります。
というのをメモしていきます。
thisはオブジェクトを指します。
オブジェクト内にconsole出力をさせる関数を作った場合に
thisが何を指すのかを見ると、
thisは親のオブジェクトを指します。
では以下のように、関数(fnc1)の中に関数(fnc2,fnc3)を書いて
その中でthisが何を指すのかを見ると...
オブ...じゃなくてグローバルオブジェクト(window)を指しました。
これは思いもよらない動作です。
オブジェクトの中にいるのに突然グローバルを指してしまうのは
JavaScript特有の癖みたいで、
この仕様を理解しておかないといけないです。
このthisの動作を知ることで、ようやくthisを代入する意味が理解できます。
例えば以下のように、最初の関数内でthisをthatに代入すると
ネストされた以降の関数でもthatにthisが保持されているのでthatをthisとして利用できます。
thatに代入する以外にも、selfに代入するのも良く見ますね。
【テンプレートエンジン】Pugでマークアップ環境を作る
- 完成図
- Pugテンプレート作成
- _inc_head.pug
- _inc_header.pug
- _inc_nav.pug
- _inc_footer.pug
- layout.pug
- index.pug
- config.pug
JavaScriptについてばかりでしたので、たまには違うメモを。
といってもなぜか、サーバーサイド寄りの内容になりますmm
前にCodePenを漁っていたら、これ↓が目に入ったのがきっかけで
気になってしょうがなくてそのままPugをずっと調べてました。
Pugは元の名がJadeで、ちょっと前にPugに名前が変わったそうです。
私も馴染みのあるHamlに影響を受けたJavaScriptテンプレートエンジンなんだそうです。
↓試しに作ったこれを元にメモしていきます。よければ見てみてください。
完成図
Pugテンプレート作成
まずテンプレートを用意します。
開発環境のルートディレクトリに
- config.pug
- layout.pug
そしてpugフォルダを作り、その中に
- index.pug
を作成し、3つの主要ファイルを用意します。
そして今回の場合、
メタ要素を入れる _inc_head.pug
コンテンツには
ヘッダー _inc_header.pug
ナビ _inc_nav.pug
フッター _inc_footer.pug
という設定です。
テンプレートは全部includeで読み込むので、includeフォルダ内に纏めます。
トップページの要素はtopフォルダ内に纏めます。
このような感じにしてみました。
_inc_head.pug
includeテンプレートから作成していきます。
まずヘッダーから、Pugはこのような書き方をします。
_inc_header.pug
この閉じタグなしで入れ子の書き方はHamlの経験があれば馴染みがあります。
%などが無くさらにスッキリです。
divは省略ができ、if文もこんな感じで書けてしまいます。
(keyやpages.top.urlなどの変数は後に出るconfig.pug内で設定してます。)
_inc_nav.pug
eachやforも使えるので、かなりシンプルになります。
リンク内にも変数を使えました。
_inc_footer.pug
最後にscriptを読み込んでますが、
jsフォルダまでのpathをconfig.pugに纏めておけば、
テンプレート内でpathが長くなることがありません。
layout.pug
layout.pugでトップページの構成を組んでいきます。
1行目の書き方でHTML5の宣言になります。
2行目,14行目にblockとありますが、varsには変数、contentsにはコンテンツの内容をindex.pug内で纏めたものを呼び出しています。
8行目のbodyクラスにkeyという変数を使っています。keyはvars内で代入しています。
index.pug
index.pug内はまずextendsでlayout.pugを継承することから始め、
block varsに変数を纏めています。(config.pug内の変数もvarsに纏めています。)
block contentsにコンテンツ内容を纏めています。
caseを使って場合によりコンテナ内が変わるようにしてみました。
ちなみに、コメントアウトは//-です。
入れ子にすれば2行以上コメントアウトできます。
config.pug
config.pugにはページ情報を書きます。
省略パスもここで設定してます。
変数を定義するときはなぜか-(ハイフン)が必要になります。
ちなみに変数を使用する場合は#{key}という書き方です。
長くなりましたが、以上でテンプレの準備は大丈夫かなと思います。
そして最後にpugをhtmlに変換します。
ここではgulpを使用しています。
npmパッケージはgulp-pugを使用すれば簡単にコンパイルができます。
【JavaScript】prototypeが何なのかをはっきりさせる
JavaScriptとはプロトタイプベースの言語ということですが、
「プロトタイプ」とは何だろう?
ということで、メモしていこうと思います。
プロトタイプはオブジェクトです。
プロトタイプは全てのオブジェクトに関連付けられています。
全てのオブジェクトはプロトタイプのプロパティを継承しています。
なので全てのオブジェクトは、プロトタイプのプロパティを使用することができます。
(※1 Object.prototypeのみプロトタイプを持ちません。)
ということで、まずプロトタイプを見てみます。
ArrayオブジェクトのプロトタイプをchromeのConsoleで出力してみました。
Arrayオブジェクトが持つプロパティがダダダーっとあって、その一番下に__proto__:Objectというものがあります。
こいつがプロトタイプです。
では、プロトタイプはどんなプロパティを持っているのかを見ると、こんな感じです。
因みに、※1 Object.prototypeのみプロトタイプを持ちません。ということを書きましたが、
Object.prototypeをConsoleで出力すると以下になります。
一個上の画像のArrayの継承している__proto__と持ってるプロパティが同じ。
ということは、Object.prototypeこそがプロトタイプなんですね。
なので、全てのオブジェクトはObject.prototypeを継承しているとも言えます。
このプロトタイプのプロパティはコードを書く際、同じ処理を再利用したり、オリジナルに拡張したりすることに利用します。
このように、Hello name♡とコンソールで出力するhelloメソッドをHumanオブジェクトのプロトタイプのプロパティに追加します。
naninu自身にhelloがあるわけではなく、Humanのprototypeにhelloを入れたので、(今回だとHumanをインスタンス化した変数naninu)naninu.__proto__.helloにあります。
ですが、naninu.hello();で呼び出すことができます。
このようにプロトタイプのプロパティを連鎖的に探し出してくれます。
(naninu.__proto__にhelloがなければ、naninu.__proto__.__proto__を探して、なければnaninu.__proto__.__proto__.__proto__を探して・・・というようにプロトタイプのプロトタイプは...と自動的に探していきます。)
これをプロトタイプチェーンと言います。
・・・長くなってしまいましたが、最後にもう一つ。
プロトタイプを使うことで何が良いのかということです。以下ダメな例になります。
このように、直接コンストラクタ関数Humanにメソッドを追加することができますが、
このようにしてしまうと、Humanをnewでインスタンス化した分メソッドの処理も入ってることになります。
先ほど"同じ処理を再利用したり..."と書きましたが、これがそうです。
同じメソッドの処理を何個も作成することで、その分メモリ領域は使用され重くなっていってしまいますが、
プロトタイプを使用することで、処理はHuman.prototype.helloを参照するだけになり、使いまわすことができます。
プロトタイプって、
後での改良を見込んで、その仕事をする大筋として作る最初の模型。
(google検索)という意味なのでそういった目的でプロトタイプを追加していけば良いですね〜。
【JavaScript】暗黙的な型変換の良い例
↑に貼っている、前回のメモのおまけの内容になります。
1つ目の実験、a, b, cの引数に3, 3, '3'と渡し、それらを足した結果をコンソールログで出した結果、63と出ました。
これはaとbはnumber型だから、問題なく足し算され6になります。
ただ、最後の'3'はstring型と認識されるので文字としてくっ付きます。
ここまでは想像通りの結果でした。
ではtypeofで型も調べてみます。
するとstringと出ました。
ん...?6はnumber型のはず、number要素はどこかに行ってしまいました。
そう、これが暗黙的な型変換みたいですね。
2つ目の実験、a, b, cの引数に'3',3, 3と渡し、それらを足した結果をコンソールログで出した結果、333と出ました。
これはaのstring型にbとcのnumber型を足し算しています。
ん...?bとcはnumber型なのに数字らしく足し算をしていないだと!?
そう、これが暗黙的な型変k(ry
先頭(ここではa)がstring型だと、後に続く(ここではb,c)number型は計算する前にstring型に暗黙的に変換されました。
1つ目と2つ目のログは、本当に信用できるのか。
この結果の63と333は今後string型として本当に利用できるのか。
以下7行目から実験しました。
厳密等価演算子で調べてもstring型と言い張るので、これはもう完全なstring型でした。
こんな事象があることを知っていれば、今後あれ?となることが減るかもしれませんね。