WebEngine

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

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サイトを柔軟にレイアウト できる比較的新しい技術ですが、一部ブラウザでは対応されてないので注意しましょう。


参考