読者です 読者をやめる 読者になる 読者になる

WebEngine

だらだらと綴る技術系メモ

vimのカラースキーマをMolokaiにしただけ

Molokaiが結構良いみたいなので

  • Macのターミナルのvimでやっています(Windowsだとおそらくキツイ)

今までデフォルトのカラースキーマで満足していたのですが、ほかの人のvimを見て「いいな」と思い導入することにしました。
続きを見てもいいですが、僕が参考にした以下のサイトを見れば一発でできると思います。(それだけ簡単だった)
ponkiti’s blog VimのカラースキームをMolokaiに変更する

手順

ターミナルを開いて、以下のコマンドを順に実行します。

$ mkdir ~/.vim
$ cd ~/.vim
$ mkdir colors
$ git clone https://github.com/tomasr/molokai
$ mv molokai/colors/molokai.vim ~/.vim/colors/

.vimという隠しディレクトリを作成し、さらにその中にcolorsというディレクトリをつくります。そこに ネットからもってきたmolokaiをぶちこみます。 続いて.vimrcvimで開きます。(なければ作成) ファイルには以下のように追記します。

syntax on
set t_Co=256
colorscheme molokai

おまけ

なんか短くなってしまったのでvim関連で自分が最近驚いたことをメモしておきます。
:e .と入力するとvim内で現在いるディレクトリのエクスプローラが表示されます。地味に 便利。

参考


今さらながら == と === の挙動の違いをチェック

そもそもコレなんて呼ぶ

PHPjavaScriptで、いつも使っているけど、何て言うのか 覚えていますか?
ネット上とかで毎回見ているけど、意外とスルーしていたりします。
正解は

うーん、会話で使うには長いんですよね。普段は、「イコール1コ抜けてるよ」 とか言っていますね。

で、名前のとおり、=== の方が厳しく型をチェックしてくれます。というわけで === の方を使う ことが、PHPjavaScriptでは、特別なケースを除いて常識になっているわけです。
でも、実際にどんな動きをしているか理解しているのか、と言われたら微妙だということに 気づきました。

挙動チェック

上がjavaScript、下がPHPのコードです。

var str = "1";
var num = 1;

console.log( str == num ); // true
console.log( str === num ); // false
<?php
$str = '1';
$num = 1;

var_dump( $str == $num ); // true
var_dump( $str === $num ); // false

== は文字列を数値に変換してから比較を行います。 === は型変換を行うことなく評価を行うので、 javaScriptPHPともにfalseが返ってきていますね。この挙動を見ただけでも === を使うことの 意味が実感できると思います。

次に、Boolean(boolean)型を見てみましょう。
オペランドの片方がBooleanならば、その論理オペランドはtrueならば1に、そしてfalseならば0に変換さます。
=== ならば、もちろん厳密にチェックしてくれるのでfalseが返って来ます。

console.log( true == 1 ); // true
console.log( true === 1 ); // false
console.log( false == 0 ); // true
console.log( false === 0 ); // false
<?php
var_dump( 1 == true ); // true
var_dump( 1 === true ); // false
var_dump( 0 == false ); // true
var_dump( 0 === false ); // false


javaScriptPHPの違い

javaScriptの方は、最後の2行に注目していただければわかると思います。

console.log( undefined == null ); // true
console.log( undefined === null ); // false
console.log( undefined == "" ); // false
console.log( undefined === "" ); // false
console.log( null == "" ); // false
console.log( null === "" ); // false
<?php
var_dump( null == '' ); // true
var_dump( null === '' ); // false

PHPの方はnullが == で比較した場合、trueになっているんですね。この挙動は最新のPHP7で確認しても 変わっていませんでした。
それでも、 === で比較すれば、ちゃんとfalseが返って来てくれます。このことからわかることは...

ちゃんと === を使いましょう、ってことですかね。

javaScriptのthis

thisイコール「自分自身」からの脱却


先にコードとコンソール(開発者ツール)での結果を出します。

<div id="test_zone">
  <button id="test_button">テストボタン</button>
</div>
$(function() {

  "use strict";

  console.log("1 : " + this);

  // Testオブジェクト
  var Test = function(score) {
    console.log("2 : " + this);
    this.score = score;
}

  // メソッドはプロトタイプ宣言で
  Test.prototype = {

    buttonOn : function() {
      console.log("3 : " + this);
      console.log("test : " + this.score);

      $("#test_zone").on({
        "click": function() {
          console.log("4 : " + this);
        }
      }, "#test_button");

    }

  };

// -- main --
var test = new Test(55);
test.buttonOn();

});
結果
1 : [object HTMLDocument]
2 : [object Object]
3 :[object Object]
test : 55
4 : [object HTMLButtonElement] // ボタンをクリック後


番号順に説明していきましょう。

1はグローバルなので、オブジェクトはHTMLDocument、つまりwindowを指しています。

2はTestオブジェクト(Testクラス)内なので、Testオブジェクト自体を指しています。

3はbuttonOnメソッド内。結果がobject Objectでわかりづらいので、Testオブジェクトの プロパティであるscoreをthisで呼びしています。scoreがthisで呼びせている、ということ は、つまり、thisにはTestオブジェクトが入っていることを意味しますね。

問題は4です。4でのthisは、HTMLButtonElementを指しています。DOMのボタン を示しているのです。

なぜか。それは、javaScriptでは関数自体が独立したオブジェクトであり、thisは関数を 定義したオブジェクトに属するものではないからです。(この説明は誤解を招くかもしれませんね。自分でも ちょっと自信ないです)

で、結局thisがなんなのかと言うと、その関数やメソッドを呼び出したオブジェクトが入っているというイメージが良い かもしれません。
4では、jQueryのonメソッドのclickメソッドを呼び出したbuttonElementがthisに 入っていたわけです。


上記の場合の解決策

上記の場合で、onメソッド内でTestオブジェクトを参照したい、という場合があります。そのような場合は、 一旦、別変数のなかにthisを格納することで解決できます。下記ではselfという変数 のなかにthisを格納しています。

buttonOn : function() {
  console.log("3 : " + this);
  console.log("test : " + this.score);

  var self = this;

  $("#test_zone").on({
    "click": function() {
      console.log("4 : " + this);
      console.log("5 : " + self);
      console.log("test : " + self.score);
    }
  }, "#test_button");

}
5 : [object Object]
test : 55


Testオブジェクトのscoreselfで呼び出せているので 5のobject Objectの正体がTestオブジェクトであることがわかります。 成功ですね。

参考

applycallを使うとthisを自由自在に操ることができる らしいです。詳しくは以下を参照してください。

広告を非表示にする

CSS3で光沢を表現する

ナビゲーションをつくる

今回は以下のナビゲーションにlinear-gradientを施す形で光沢を表現します。

f:id:web-engine:20161101150726p:plain

コードは以下の通り。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>DEMO</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>

<nav>
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Works</a></li>
    <li><a href="#">Links</a></li>
  </ul>
</nav>

</body>
</html>


body {
  margin: 0;
  padding: 0;
}

nav {
  background-color: #ddd;
}

nav ul {
  overflow: hidden;
  list-style: none;
}

nav li {
  float: left;
  width: 100px;
  border-right: #fff 1px solid;
  font-weight: 700;
}

nav li:first-child {
  border-left: #fff 1px solid;
}

nav a {
  display: block;
  text-decoration: none;
  text-align: center;
  background-color: #f36;
  padding: 10px 0;
  color: #fff;
}

nav a:hover {
  opacity: 0.7;
}


見てわかる人もいるかもしれませんが、前回の記事のコードをちょっと加工しただけです。

ナビゲーションに光沢を施してみる

CSSに以下の記述を追加します。

nav a {
  display: block;
  text-decoration: none;
  text-align: center;
  background-color: #f36;
  padding: 10px 0;
  color: #fff;

  /* ここから先を追記 */

  background: -webkit-linear-gradient(
    top,
    #ffced7 0%,
    #f74657 49%,
    #f10013 51%,
    #fe2951 100%
  );
  background: -ms-linear-gradient(
    top,
    #ffced7 0%,
    #f74657 49%,
    #f10013 51%,
    #fe2951 100%
  );
  background: linear-gradient(
    to bottom,
    #ffced7 0%,
    #f74657 49%,
    #f10013 51%,
    #fe2951 100%
  );

  /* ここまで追記 */

}


以下はGoogle chromeでの表示結果です。

f:id:web-engine:20161101150748p:plain

ベンダープレフィックスをつけているので、FireFoxとIE10以上でも表示されます。その 他のブラウザでは確認していません。
linear-gradientはIE9以下ではサポートされていません。F12ボタン(Windowsの場合)を 押して開発者ツールでブラウザのバージョンを下げれば、そのことがわかります。

linear-gradientの注意点

上記コードでlinear-gradientを施した際、ベンダープレフィックスつきの書式と、ついていない書式で違う部分が あります。(それ以外は同じということなのでコピペが有効)
topto bottomの部分ですね。今回のグラデーションの場合、上から下へのグラデーションと なっているわけですが、linear-gradientでは、プレフィックスつきの場合は起点の名前を、そうでない (ベンダープレフィックスではない)場合は、to ××で方向を指定します。

上記のナビは光沢にするため%なんかを使っていますが、基本形は下記のような感じになります。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>DEMO</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div id="grad_box"></div>
</body>
</html>


body {
  margin: 0;
  padding: 0;
}

#grad_box {
  width: 200px;
  height: 200px;
  background: #ddd;
  background: -webkit-linear-gradient(top, #ffced7, #fe2951);
  background: -ms-linear-gradient(top, #ffced7, #fe2951);
  background: linear-gradient(to bottom, #ffced7, #fe2951);
}


f:id:web-engine:20161101150803p:plain

現在ではフラットデザインが主流となっているので使用場面が限られますが、それでも覚えておいて損はないはずです。

よく使うdisplayプロパティまとめ

displayプロパティとは?

displayプロパティはCSS3において、要素の表示特性を操作するものです。たとえば、ブロック要素をインライン要素に 変更したり、その逆にしたりすることが可能です。(HTML5ではブロック要素やインライン要素といった分類は廃止されましたが説明 を簡単にするため省略します)

よく利用されるのがa要素のブロック化ですね。下記のコードはブロック化する前のリンクです。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>DEMO</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>

<nav>
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Works</a></li>
    <li><a href="#">Links</a></li>
  </ul>
</nav>

<body>
</html>


body {
  margin: 0;
  padding: 0;
}

nav {
  background-color: lightgreen;
}

nav ul {
  overflow: hidden;
  list-style: none;
}

nav li {
  float: left;
  width: 100px;
  border-right: #fff 1px solid;
}

nav li:first-child {
  border-left: #fff 1px solid;
}


f:id:web-engine:20161030193936p:plain

a要素がブロック化されていないと、このようにリンクとして作用するのは文字に触れているあいだだけになります。a要素がデフォルトでは display: inline;になっているからです。
この問題を解決するためにa要素にdisplay: block;を指定してみましょう。CSSに次のように追加します。

nav a {
  display: block;
  text-decoration: none;
  background-color: orange;
  padding: 10px 0;
}

nav a:hover {
  background-color: green;
}


f:id:web-engine:20161030193953p:plain

a要素がブロック化されていることを証明するためにオレンジ色を施しました。また、文字に触れていなくても、領域全体が クリック可能になっていることが緑色でわかるはずです。paddingで幅と高さが指定できるようになっているのも わかりますね。

ちなみに、ここではnavに直接CSS指定を指定していますが、実際はidclassで指定しましょう。

主要なもの

displayプロパティの種類は結構多いですが、とりあえず以下の4つが基本です。

  • block
    • float, position等を指定しない限りは配置された要素は自動改行され、上から下へ並ぶ
    • width, heightが指定可能
    • margin, paddingが指定可能
    • vertical-alignプロパティ指定不可


  • inline
    • br要素で改行されない限り、テキストと同じように横並びになる
    • width, heightが指定不可
    • 上下marginが指定不可
    • vertical-alignプロパティ指定可能


  • inline-block
    • 上記のinlineと同じく、横並びになる
    • width, heightが指定可能
    • margin, paddingが指定可能
    • vertical-alignプロパティ指定可能
    • 親要素のtext-alignでボックスどうしの上下の方向を揃えることが可能


  • table-cell
    • 要素が一列に横に並ぶ(th, tdのようになる)
    • 隣りあう要素の高さは自動的に最も高い要素に揃えられる
    • vertical-alignプロパティ指定可能
    • 親要素にdisplay: table;を指定した上で、その要素にwidth指定を行うと、これを指定 した要素が親要素の幅に合わせて自動で伸縮するようになる


たまに使うもの

  • table
    • 上記で出てきたtable-cellとセットで使うことが多い
    • ブロックレベルボックスとして配置される表(tableをそのままイメージしてもらえれれば良い)


  • list-item
    • リスト項目として表示
    • ブロックレベルとして配置される


  • none
    • 要素事態を非表示にしてしまう(ないものとしてしまう)
    • 指定された要素の空白領域は確保されず、後続要素が上に詰めて表示される。


最近の主流

display: flex;と表記することでフレキシブルボックス化することができます。これを利用した デザインはフレキシブル・ボックス・レイアウトなんて呼ばれるみたいです。複雑なwebサイトを柔軟にレイアウト できる比較的新しい技術ですが、一部ブラウザでは対応されてないので注意しましょう。


参考


JavaScriptでオブジェクト指向プログラミング

JavaScriptの特徴

JavaScriptは立派なオブジェクト指向言語です。ただし、Javaなんかのオブジェクト指向言語とは かなり異なる部分があり、オブジェクト指向を知らない初心者がJavaScriptから勉強しはじめると 混乱に陥ります。
まず、JavaScriptにはクラスがありません。かわりにプロトタイプと呼ばれるものが存在します。 ただし、このプロトタイプという言葉自体が混乱を招く結果にもなっていると僕は思います。なので、ここでは便宜上、 プロトタイプのことをクラス、あるいはオブジェクトと呼ぶこととします。

あと、以下のプログラムはGoogle chromefirefoxでしかテストしていません。念のため。

空のクラスを定義

まずTestクラスを実装してみます。

var Test = function() {
  // プロパティ、メソッドなどをこの中に記述
};


これがJavaScriptのクラスです。見てのとおり、厳密にはクラスではありません。関数にクラスとしての役割を与えることで クラスっぽい挙動をさせるのです。
ちなみにクラスなので変数の最初は大文字です。そうしないと混乱を招くので必ずそうしましょう。

インスタンス化は

var test = new Test();

と記述します。これは他言語と同じような感じですね。

プロパティとメソッドを実装

では上記のクラスにプロパティ、メソッドを書いてみましょう。

var Test = function(name, score) {

  // プロパティ(Javaだとフィールドにあたる)
  this.name = name;
  this.score = score;

  // メソッド
  this.getData = function() {
    return this.name + " : " + this.score;
  }

};


こんな感じになります。
メソッドに注目してください。これはメソッドというよりはプロパティに関数を突っ込んでいるだけ、とも 言えます。実際、JavaScriptではメソッドという概念があるとは言えず、値が関数であるプロパティが メソッドとしてみなされます。しかし、大体どこでもメソッドと言っている気がしますし、ここでもメソッドで通します。
あと、直観でわかる人もいると思いますがthisは自分自身(ここではTestクラス自身)です。(正確には、JavaScriptのthisは、 Javaなんかとちょっと違うのですが、ここでは割愛します)

本当に呼び出せるか実際に実行してみます。

var test = new Test("hoge-kun", 75);
console.log(test.getData());


hoge-kun : 75と表示されればOKです。

メソッドの後づけ定義

JavaScript一旦インスタンス化させたオブジェクトに対し、新しくメソッドを追加することができます。
言っている意味がわからない人も多いと思いますので具体例を出します。

var Test = function(name, score) {

  this.name = name;
  this.score = score;

  this.getData = function() {
    return this.name + " : " + this.score;
  }

};

var test = new Test("hoge-kun", 75);

// 名前だけ返すgetNameメソッドを追加
test.getName = function() {
  return this.name;
}

console.log(test.getName());


ちゃんとhoge-kunとだけかえってきましたか?
こんなことできていいのかよ、と他言語を使っていた人なら思うでしょう。
これがJavaScriptの柔軟性であり、同時にバグが混入しやすくなる原因でもあります。

たとえば、下記のコードを見てみましょう。

var Test = function(name, score) {

  this.name = name;
  this.score = score;

  this.getData = function() {
    return this.name + " : " + this.score;
  }

};

// hoge-kunとfuga-chanのTestオブジェクトをインスタンス化
var test_hoge = new Test("hoge-kun", 75);
var test_fuga = new Test("fuga-chan", 90);

// 変数test_hogeだけに、名前だけ返すgetNameメソッドを追加
test_hoge.getName = function() {
  return this.name;
}

console.log(test_hoge.getName());
console.log(test_fuga.getName());


TypeError: test_fuga.getName is not a functionといったような エラーが返ってきたはずです。そう、メソッドを追加したのは変数test_hogeだけであり、test_fugaには追加 されていないからです。
このようにJavaScriptでは、同じクラスのもとにインスタンス化されたオブジェクトであろうと、それぞれのインスタンスが持つメソッドは 同じとは限らないのです。

メソッドはプロトタイプで宣言しよう

先にコードを出します。

// -- Testクラス(Testオブジェクト) --

// プロパティ(フィールド)はTestクラスをつくったときに
var Test = function(name, score) {
  this.name = name;
  this.score = score;
};

// メソッドはprototypeプロパティへ入れる
Test.prototype = {
  getData : function() {
    return this.name + " : " + this.score;
  },

  getName : function() {
    return this.name;
  }

};
// -- Testクラスここまで(実際はここまででファイルを分ける) --

// -- ここからメイン処理 --
var test_hoge = new Test("hoge-kun", 75);
var test_fuga = new Test("fuga-chan", 90);

console.log(test_hoge.getName());
console.log(test_fuga.getName());


今回はhoge-kun fuga-chanがともに返ってきます。これがJavaScriptオブジェクト指向の完成形・・・というわけでは ないのですが、とりあえずそうしておいてください。少なくとも僕はこう書いています。
この急に出てきた 「prototypeってなに?」 「なんでクラスのなかにメソッド入れてしまわないの?」 と思われる方 もいると思いますが、これを使うといろいろ利点があります。その内の一つが

メモリ消費を抑えることができる

です。

インスタンスは生成するたびに、それぞれのインスタンスのためのメモリを消費します。メソッドをプロトタイプ宣言で追加する前のコードでは、 メソッドをインスタンス化のたびにコピーしていたわけです。

f:id:web-engine:20161023190700p:plain

これらのメソッド群をprototypeプロパティで追加すると、オブジェクトをインスタンス化したとき、インスタンスはそれぞれ個別のメソッドを 持つわけではなく、もととなったprototypeオブジェクトを参照することとなります。
図で説明するとこんな感じですね。

f:id:web-engine:20161023190721p:plain

毎回メソッドをコピーするわけではなく同じアドレスを見に行っているだけなので、結果としてメモリ節約になるわけです。

ちなみに、上記コードでメソッドをprototypeプロパティへ格納していますが、この手法はオブジェクトのリテラル表現を使っています。

基本形は

var Test = function() { // プロパティ };
Test.prototype.getData() { // 処理 };
Test.prototype.getName() { // 処理 };


のように書きます。しかし、これでは修正箇所が多くなるので、以下のように書くと良いでしょう。

var Test = function() { // プロパティ };
Test.prototype = {
   getData : function() {
    // 処理
  },

  getName : function() {
    // 処理
  }
  
};


読みやすくもなって一石二鳥です。

カプセル化は面倒くさい

PHPの場合

<?php
class Test {

  private $name;
  private $score;

  function __construct($name, $score) {
    $this->name = $name;
    $this->score = $score;
  }

  // $nameは、このメソッドを通しでしか参照できない
  public function getName() {
    return $this->name;
  }

  // Testクラス内でしか呼び出せないメソッドの処理
  private function secretMethod() {
    // 処理
  }

}


のようにしてメソッドなどを自分自身のクラス内でしか呼び出せないようにします。$name$scoreも パブリックメソッドを通してでしか参照できないようにできます。クラスを設計する際は、通常このようにして 安全性を向上させます。これが俗に言うカプセル化です。

JavaScriptではデフォルトで、すべてのメンバがパブリックになっています。そして、JavaScriptでも カプセル化を施すことは可能です。
可能なんですが、ちょっと面倒くさいというか、コードが非常に冗長的になるというか・・・。

どうしても仕事で使っていてプライベートメンバにして「危険を取り除きたいんだ!」という方は、ほかの人が良い 方法を書いてくれているはずなので検索してみてください。(投げやり)


静的プロパティ・メソッドの定義

静的プロパティ、静的メソッドとは、インスタンス化せずともオブジェクトから直接呼び出せるプロパティ、メソッド。 グローバル変数、関数を減らすために使用されることが多いです。
以下のように実装します。

/*
 -- 構文 --
 オブジェクト名.プロパティ名 = 値;
 オブジェクト名.メソッド名 = function() { 処理 };
*/

// クラス定義
var StaticTest = function() {};

// 静的プロパティ定義
StaticTest.VERSION = "2.0";

// 静的メソッド定義
StaticTest.returnName = function () {
  return "STATIC_TEST!";
};

// -- メイン処理 --
console.log(StaticTest.VERSION);
console.log(StaticTest.returnName());

var static_test = new StaticTest();
console.log(static_test.returnName()); // エラー


インスタンス経由で静的メソッドを呼び出そうとするとエラーになるはずです。

上記のエラーからわかるように、静的プロパティ及びメソッドを定義する際は、プロトタイプオブジェクトには追加できません。 プロトタイプオブジェクトはインスタンスから直接参照されることを前提としたものだからです。

PHPでJSONを扱う

JSONってなに?

JSON(JavaScript Object Notation)は、テキストフォーマットの一種です。シンプルで 開発者が理解しやすい構造をしており、コンピュータにとっては高速で処理しやすいというすぐれもの。
WebAPIなどを使って引っ張ってくる形式のファイルはCSVXMLJSONのうちどれかですが、 最近の主流はJSON。構造がJavaScript連想配列と似ている(というかそのまま?)ので、はじめて 見る人でも理解しやすい。


PHPJSON処理

下記のようなjsonファイルを用意しました(test.json)。ゲームなんかで使えそうな タイプです。

{
"id" : 24,
"name" : "勇者A",
"status" :
    {
        "hp" : 175,
        "mp" : 50
    },
"item" :
    {
        "money" : 25000,
        "sword" : [
            {
                "name" : "錆びた剣",
                "atk_point" : 50
            },
            {
                "name" : "ライトセーバー",
                "atk_point" : 350
            }
        ]
    }
}

これをPHPで処理します。具体的には下のコードを参照してください。

<?php
$pass = "test.json";
$json = file_get_contents($pass);
if (!empty($json)) {
  $json = mb_convert_encoding($json, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');

  // 連想配列として扱いたい場合は、第2引数にtrueを渡す
  $obj = json_decode($json);
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <title>TestJSON</title>
  <meta charset="utf-8">
</head>
<body>

<p>ID: <?=$obj->id?></p>
<p>名前: <?=$obj->name?></p>
<p>HP: <?=$obj->status->hp?></p>
<p>MP: <?=$obj->status->mp?></p>
<p>所持金: <?=$obj->item->money?></p>

<?php foreach ($obj->item->sword as $val): ?>
  <p>剣の名前: <?=$val->name?></p>
  <p>剣の攻撃力: <?=$val->atk_point?></p>
<?php endforeach; ?>

</body>
</html>

WebAPIなんかを利用する場合は$passの部分にURLを書きます。今回はなるべくシンプルにした かったのでこのようなコードになりました。コメントアウトにもあるとおり、連想配列として扱いたい場合、 json_decode()の引数にtrueを渡してやります。 僕はオブジェクトとして扱う方が好きなので 今回は使っていません。

$ary = json_decode($json, true);


説明するまでもないですが、これでjsonの内容がすべて出力されます。

広告を非表示にする