Published on

JavaScript基礎

Authors
  • avatar
    Name
    Kikusan
    Twitter

Doc: MDN

Tips

  • 一般的に変数・関数:camelCase 定数:SNAKE_CASE クラス:PascalClass

JSの呼び出し

<!-- JSファイルの実行-->
<script type="text/javascript" src="script/index.js"></script>
<script>
    //危険な構文を禁止する
    'use strict';
    //HTMLへの埋め込み
    alert('インラインスクリプト');
</script>
<a href ="JavaScript:window.alert('アンカータグからこんにちは');">

<noscript>JavaScriptが利用できません。</noscript>

変数・定数

//変数 letは変数重複を許可しない スコープもletはブロックレベル、varは関数レベル
let msg = 'hoge';
//定数
const TAX_RATE = 0.10;

データ型概要
number数値
string文字列
boolean真偽
objectオブジェクト(参照型)
function関数(参照型)
などなど
let array = ['js', 'html'];
console.log(list[0]);  //js

//連想配列{キー:プロパティ}
let obj = {x:1, y:2, z:3};
console.log(obj.x);  //1
console.log(obj['x']);  //1

null:空であること。 戻り値がある関数で返せないときとか。 undefined:未定義であること。未定義プロパティや、宣言だけの変数、戻り値のない関数の戻り値

演算子

console.log(10 + 1); //11
console.log('10' + '1'); //101
console.log(1234 + Date()); //1234日付
let x = 3;
let y = x++; //y=3 x = 4 ++ を前にすると反映
5 == 5 //true
5 != 5 //false
5 === 5 //true(データ型も一緒)
(x==1) ? 1 : 0 //三項演算子
5 === 5 && 10 === 10 //true
5 === 5 || 10 ===1 //true
!(10 > 11) //true

制御構文

if(条件式){
    //処理
} else if(条件式){
    //処理
} else {
    //処理
}

switch(){
    case1:
        //処理
    break;
    //breakないと下まで流れる
    case2:
        //処理

    default:
        //処理

while(条件式){
    //処理
}

do{
    //処理
}while(条件式);

for(let i = 2; i < 10; x++){
    //処理
    if(...){
        //次
        continue;
    } else if(...){
        //抜ける
        break;
    } else if(...){
        //ラベル
        break pass;
    }
}
pass:

//カンマで複数でける
for(let i = 1, j = 1; i < 3; i++, j++){
    //処理

}

//for in of イテレータのプロパティをすべてループできる
//inは連想配列のキーや配列のインデックスを取る
for(key in map){
    console.log(key);
}
//ofはvalueを取る
for(value of map){
    console.log(value);
}

例外処理

let i = 0;
try{
    //自作例外を投げる
    if(i = 0) {throw new Error('エラー');}
} catch(e){
    console.log(e.message);
}finally{
    //絶対行う処理
}

オブジェクト

オブジェクト=プロパティ+メソッド NumberやStringなどの基本データ型もラッパーオブジェクトは存在するが、 自動的に相互変換してくれるので開発者が意識する必要はない。

// object constにしても参照なので中身更新は可能
const person = {
    name: 'Mike',
    ary: [18, 'sales'],
    obj: {
        sports: 'soccer',
        hobby: 'anime'
    },
    getHobby: function () {
        console.log(this.obj.hobby);
    }
};
person.ary[0] = 20;
person.obj['sports'] = 'baseball';
console.log(person.ary);

配列

let ary = [1,2,3, 'str', False];
//コンストラクター経由配列
let ary = new Array(1,2,3);
let ary2 = new Array(10); //サイズが10
// forEach 無名関数の引数に配列のvalue, index, イテレータそのものが入る
arry.forEach(function(val, i, ary) {
    console.log(val + 1 + ary);
});
// reduce それぞれの要素の蓄積 accu:returnの内容, curr:現在の要素
arry.reduce(function(accu, curr) {
    console.log(accu, curr);
    return accu + curr;
}, 2/* 最初の戻り値の初期値 */);
//同じような形でmap, some, filter, sortメソッドがある。配列を返したり要素を絞ったり、、、

map

オブジェクトリテラルで連想配列は使えたが、ES6でオブジェクトとして使えるようになった? 任意の型をキーとして使えるのがいいところ

//new Map([[キー, 値],[キー, 値],...])
let ma = new Map();
ma.set(1, 'hoge');
console.log(ma.get(1));

Set

重複なしの配列みたいな

let se = new Set([1,2,3]);

Date

加減、差分を求めるような関数はないらし

let d = new Date();
//三か月引く
d.setMonth(d.getMonth -3);

関数

JSでは関数もオブジェクト return句の後ろは実行されない。Exitはreturn。 引数省略も、戻り値なしならreturn省略もできる。 呼び出し時には引数の数はチェックされない(足りなきゃundefined)

//function命令
function myfunc(引数...){
    //処理
    return 戻り値;
}
myfunc();

//コンストラクター経由
let myfunc = new Function('num', 'return num * num;');
myfunc(30);

//コールバック関数 名前のない関数を変数に格納する
let myfunc = function(num){
    return num * num;
};

//アロー関数 関数リテラル表現の進化版
//(引数) => {関数の中身}
//引数一つなら()を省略できる。引数なしなら()
let myfunc = (num) =>{
    return num * num
};

オブジェクト指向

class Animal { 
    // コンストラクター 
    constructor(name, age) { 
        this.name = name;
        this.age = age; 
    } 

    //静的メソッド
    static getAge(){
        return age;
    }

    // メソッド 
    getName() { 
        return this.name;
    }

    //get構文
    get name(){
        return this._name;
    }

    //set構文
    set name(name){
        this._name = name;
    }
}
let a = new Animal('dog'); 
console.log(a.getName()); //dog

//継承
class Dog extends Animal{

    constructor(name,age, legs){
        //親クラスのコンストラクター
        super(name, age);
        //プロパティ追加
        this.legs = legs;
    }

    bark(){
        console.log('bowwow!');
    }

    //オーバーライド
    getName(){
        return super.getName() + 'という犬です'
    }
}

モジュール

1つのファイルをモジュールとして定義する。 外部参照されるものはexport文を付ける(クラスでも変数でもなんでも)

export class Animal(){...}

呼び出し側はimport文で取り出せる

import * as app from './lib/Util'  
//import(name, ...) from module

let a = new app.Animal();

DOM

Document Object model マークアップ文書を階層構造で扱う。 id, name, class, Tag名などで要素を取得し、プロパティを操作できる。

// querySelectorはDOMオブジェクトの中をセレクタで検索する
let title = document.querySelector('#title');
let divList = document.querySelectorAll('div');
// それぞれのプロパティにアクセスできる
console.log(title.innerHTML);
let child = title.childNodes;
title.classList.add('title');
// Allのときはイテレータとして使える
divList.forEach(div => console.log(div.innerHTML));

イベントドリブンモデル

ブラウザ上のイベントに乗じてJSを動かす。

タグ内属性としてイベントを宣言する

<!-- onclickに関数名を書く -->
<input type="button" value="アラート表示" onclick="btn_click()"/>
function btn_click(){
    window.alert('buttonクリック');
}

要素オブジェクトのプロパティとして宣言する

<input id="btn" type="button" value="アラート表示"/>
//ページ読み込み時に実行されるイベント
window.onload = function(){
    //ボタンクリックで実行されるイベント
    document.getElementById('btn').onclick = function(){
        window.alert('buttonクリック');    
    }
}

addEventListenerメソッドで宣言する

これを使うと一つの要素に複数のイベントハンドラーを紐づけられる

<input id="btn" type="button" value="アラート表示"/>
const btn = document.querySelector('#btn');
btn.addEventListener('click', function() {
    this.style.backgroundColor = 'aqua';
});
// thisは直近で呼ばれているオブジェクト
// ...function(){}.bind(this) とすればこのメソッド内のthisは全てメソッドを持っているオブジェクトになる。

// Load
// DOMContentLoadedはDOMツリーを作成し終わった後
document.addEventListener("DOMContentLoaded", function () {});
// loadはCSSや画像など全てダウンロードし終わった後 windowにしか登録できない
window.addEventListener('load', function() {});

Webストレージ

CookieやセッションのクライアントにJSで保存できるもの localStorage:ホスト名:ポート番号に一意で、削除しない限り残る sessionStorage:ブラウザが開いている間だけ残る。タブ間で共有もできない

別のオリジンにはアクセスできないが、script要素でURLを書いておくといけるらし

let srotage = localStorage;
storage.setItem('キー1','値1');
storage.key2 = '値2';
storage.['キー3'] = '値3';

console.log(storage.getItem('key2'));  //値2

Ajax

サーバと非同期通信をし、DOMに反映するしくみ

document.addEventListener('DOMContentLoaded', function(){
    document.getElementsById('btn').addEventLister('click',function(){
        let result = document.getElementById('result');
        let xhr = new XMLHttpRequest();
        //onreadystatechangeは通信の状態が変化したときのイベントハンドラープロパティ
        xhr.onreadystatechange = function(){
            //readyStateはHTTP通信の状態を取得するプロパティ
            if(xhr.readyState === 4){
                //statusはHTTPステータスコードを取得するプロパティ
                if(xhr.status === 200){
                    //responseTextはレスポンスをプレーンテキストで取得するプロパティ
                    result.textContent = xhr.responseText;
                } else {
                    result.textContent = 'Error...';
                }
            } else {
                result.textContent = 'Now roading...';
            }
        };
        //open(method, url, async, ...) HTTPリクエストを初期化 asyncは非同期通信か default= true
        xhr.open('GET', 'url?name=' + encodeURIComponent(document.getElementById('name').value), true);
        //send(body) HTTPリクエストを送信
        xhr.send(null);
    }, false);
},false);

POSTのときは ・Content-Typeでリクエストデータの型を示す。 ・データはsendの引数にする。

xhr.open('POST', 'url', true);
xhr.setRequestHeader('Conent-type','application/x-www-form-urlencoded;charset=UTF-8');
xhr.send('name=' + encodeURIComponent(document.getElementById('name').value));

・jsonパース

let data = JSON.parse(xhr.responseText);