0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Javascript] [TypeScript] 実装で見返す用のまとめ

Last updated at Posted at 2020-12-06

はじめに

普段はC#を使っている者が、JavaScriptとTypeScriptを学んで今後実装する上で気をつけたいことをまとめました。

以下の技術同人誌から学んだことを中心に追加で調べたことなどをまとめています。
りあクト! TypeScriptで始めるつらくないReact開発 第3版【Ⅰ. 言語・環境編】 - くるみ割り書房 ft. React - BOOTH

JavaScript

もともとはブラウザ上で動く言語だったが、Node.jsなどを使えばサーバー上にアクセスできるようになりサーバーサイドでも動くようになった。
JSX(独自のタグ技術)は、JavaScriptの拡張構文であり、コンパイルするとJavaScriptに変換される。
JavaScript | MDN

ブラウザ上で試したい時

アカウント登録なしで手軽に試せる。
JSFiddle - Code Playground

他にもいろいろあるみたいです。
ブラウザ上でJavaScriptの実行ができるサービスまとめ - Qiita

関数

// 関数宣言文
// 非推奨: 同じ関数名だと再宣言出来てしまうこと、宣言する前に呼び出し可能であることから
function multiply(x, y) {
   return x * y;
}

// Functionコンストラクタで定義した関数
// 非推奨: 常にグローバルスコープで実行されることから
var multiply = new Function('x', 'y', 'return x * y');

// 関数式
// ES2015以降はアロー関数式が推奨
const multiply = function(x, y) {
   return x * y;
};

// アロー関数式
// ES2015で追加。
// 推奨: 関数外のスコープのthisが使われるためクラス構文の時に分かりやすいから
// 再宣言や宣言する前に代入ができないようにconstにしておくこと
const multiply = (x, y) => {
   return x * y;
};

関数 - JavaScript | MDN 参照。

残余引数(Rest Parameters)

引数の名前に ... のプレフィックスを付けることで不定数の引数を配列として表す。
Array インスタンスなので、sort, map, forEach, pop などのメソッドを直接適用できる。

function myFun(a,  b, ...manyMoreArgs) {
  console.log("a", a)
  console.log("b", b)
  console.log("manyMoreArgs", manyMoreArgs)
}

myFun("one", "two", "three", "four", "five", "six")
// console output:
// a, one
// b, two
// manyMoreArgs, [three, four, five, six]

残余引数 - JavaScript | MDN

スプレッド構文

引数や配列リテラルの要素の名前に ... のプレフィックスを付けることで配列式や文字列などを展開する。
オブジェクトリテラルを展開することもできる。

function sum(x, y, z) {
  return x + y + z;
}

const numbers = [1, 2, 3];
const obj = { red: 1, blue: 2, yellow: 3 };
const obj2 = { ...obj, green: 4 };

console.log(sum(...numbers));
console.log(obj2);
// console output:
// 6
// Object { red: 1, blue: 2, yellow: 3, green: 4 }

スプレッド構文 - JavaScript | MDN

プロトタイプベース

どのオブジェクトもプロトタイプと呼ばれる、他のオブジェクトへの内部的な繋がりを持っています。
そのプロトタイプオブジェクトも自身のプロトタイプを持っており、あるオブジェクトのプロトタイプが null に到達するまでそれが続きます。
継承とプロトタイプチェーン - JavaScript | MDN から引用。

Javaなどのクラスベースと違い、実態のあるオブジェクトを継承していることになる。

var o = new Foo();

これを呼び出したとき、 JavaScript は、

var o = new Object();
o.[[Prototype]] = Foo.prototype;
Foo.call(o);

実際にはこれ(あるいはこのような何か)を行っており、

o.someProp;

後にこうすると、 o が someProp プロパティを持っているかどうかを調べ、もし持っていなければ Object.getPrototypeOf(o).someProp を、そこにも存在しなければ Object.getPrototypeOf(Object.getPrototypeOf(o)).someProp を…と調べていきます。
null は、プロトタイプを持たず、プロトタイプチェーンの最終リンクとなります。
継承とプロトタイプチェーン - JavaScript | MDN から引用。

コンストラクタ関数は、プロトタイプオブジェクトを継承して新しくオブジェクトインスタンスを生成するための関数ということになる。

オブジェクトプロパティのショートハンド

ES6では、オブジェクトリテラルの定義するときにオブジェクトのプロパティ値の記載を省略できる。
プロパティ名がキーと一致しているときのみショートハンドが使える。

// 通常
const obj = { x:x, y:y };

// ショートハンド
const obj = { x, y };

あなたが知らないJavaScriptの便利すぎるショートハンド19選 – WPJ

分割代入

配列から値を取り出す、またはオブジェクトからプロパティを取り出して別の変数に代入ができるようになる。
Reactの開発でも良く見かける。


const user = {
    id: 42,
    is_verified: true
};

const {id, is_verified} = user;

console.log(id); // 42
console.log(is_verified); // true 

分割代入 - JavaScript | MDN

this

メソッドとして実行した時はアクセス演算子.の前のオブジェクトが、new演算子をつけた時newによって新規に生成されたオブジェクトがthisになる。
関数内にないトップレベルのコードや関数をオブジェクトのメソッドでなくオブジェクトとして呼ぶと、thisはグローバルオブジェクトになる。
Global object (グローバルオブジェクト) - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN

JavaScript の this を理解する多分一番分かりやすい説明 - Qiita
👻globalThis👻と🌏global🌏と🌝this🌝 - Qiita

Strict モード

ES5で追加。
ファイルの先頭行や関数の最初に 'use strict' を記述することで有効になる。
任意のオブジェクトのコンテキストがない場合(関数をオブジェクトのメソッドでなくオブジェクトとして呼ぶ)、this が undefined になる。クラス構文内の関数でのthisもグローバルオブジェクトではなくundefinedになる。
Strict モード - JavaScript | MDN

クロージャ

クロージャは、組み合わされた(囲まれた)関数と、その周囲の状態(レキシカル環境)への参照の組み合わせです。言い換えれば、クロージャは内側の関数から外側の関数スコープへのアクセスを提供します。JavaScript では、関数が作成されるたびにクロージャが作成されます。
関数の中で定義された関数をクロージャ、外側の関数をエンクロージャと呼ぶ。

クロージャ - JavaScript | MDN


function makeFunc() {
  const name = 'Mozilla';
  function displayName() {
    alert(name);
  }
  return displayName;
}

const myFunc = makeFunc();
myFunc();

myFuncを定義時にエンクロージャmakeFuncによってクロージャdisplayNameのインスタンスの参照が返されている。
そのため、変数nameがGCに回収されず残っている。

TypeScript

AltJSであり、ビルド時にはJavaScriptに変換される。独自のコンパイラを所持している。
TypeScriptは、JavaScriptで型定義、インターフェイス、クラス、null/undefined safeに出来る・使えるようになるなどJSの上位互換といわれている。
特に型定義によって、実行前のビルド時にエラーやバグを検知することが出来ることが大きい。
MicroSoft産。
TypeScript: Typed JavaScript at Any Scale.
Introduction - TypeScript Deep Dive

Reactでは、公式で大きな規模での開発時はTypeScriptの使用を薦めている。
静的型チェック – React

ブラウザ上で試したい時

アカウント登録なしで手軽に試せる。
TypeScript Playground

npmパッケージをインストールせずrequireして使える。
Runkit + npm

型について

きちんと型のnull安全性を保障するには、tsconfig.json ファイルにコンパイラオプション strictNullChecks を設定する必要がある。
strictNullChecksの他にも便利なオプションを含んだstrictオプションを有効にすると便利。

型の互換性は、構造的サブタイピング(Structural Subtyping)に基づいており、下記のように型の構造が合致していればエラーにならない。

interface Named {
  name: string;
}

class Person {
  name: string;
}

let p: Named;
// OK, because of structural typing
p = new Person();

TypeScript: Handbook - Type Compatibility

TypeScriptの型入門 - Qiita

クラス

クラスを定義すると、「クラスインスタンスのインターフェース型宣言」と「コンストラクタ関数の宣言」が同時に実行される。
よって、TypeScriptでインポート/エクスポートするときもデフォルトでは型とオブジェクトの両方を同時にインポート/エクスポートする。
詳しくはTypeScript: Handbook - Classes を参照。

クラスの型は、インスタンスではなく下記の型エイリアスで定義する。

type Tree<T> = {
  value: T;
  left?: Tree<T>;
  right?: Tree<T>;
};

型エイリアスは、任意の型に別名を与えて再利用できるようになっている。
TypeScript: Handbook - Advanced Types

インターフェースとType

インターフェースはクラスやオブジェクトの型を宣言するが、Typeは無名の型に別名を付けるといったコンパイルの解釈の違いがある。
機能にも違いがあり、インターフェースは、同じ名前のインターフェースに新しいプロパティがある場合、型定義が追加される。一方、Typeは同じ名前のTypeは宣言できない。
他の違いなど詳しくは、TypeScriptのInterfaceとTypeの比較 - Qiita を参照。

ユニオン型

演算子|を挟んで型を並べるといずれかの型が適用される複合的な型が定義できる。

function padLeft(value: string, padding: string | number) {
  // ...
}

const str = padLeft("Hello world", '1'); // OK
const num = padLeft("Hello world", 1); // OK

TypeScript: Handbook - Unions and Intersection Types

リテラル型

JavaScriptのプリミティブのように任意の値(文字列または数値、boolean)以外代入させない型。
ユニオン型と組み合わせ演算子|を挟んで型を並べるといずれかの型が適用される複合的な型が定義できる。
enumよりコンパイル後のコードが短いためこちらが使われることが多い。


type CardinalDirection =
    | "North"
    | "East"
    | "South"
    | "West";

function move(distance: number, direction: CardinalDirection) {
    // ...
}

move(1,"North"); // Okay
move(1,"Nurth"); // Error!

リテラル型 - TypeScript Deep Dive 日本語版

Const アサーション

定数に型注釈を付与してくれる。


const Colors = {
  red: "RED",
  blue: "BLUE",
  green: "GREEN"
} as const;

TypeScript: Handbook - TypeScript 3.4

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?