TypeScript Deep Dive 日本語版
  • TypeScript Deep Dive 日本語版
  • TypeScript入門 & 環境構築
    • なぜTypeScriptを使うのか?
  • JavaScript
    • 等価演算子の同一性
    • リファレンス
    • nullとundefined
    • this
    • クロージャ
    • Number型
    • Truthy
  • モダンなJavaScriptの機能
    • クラス
      • Classes Emit
    • アロー関数
    • 残余引数(Restパラメータ)
    • let
    • const
    • 分割代入
    • スプレッド演算子
    • for...of
    • Iterator
    • テンプレートリテラル
    • Promise
    • ジェネレータ
    • async await
  • プロジェクトの環境設定
    • コンパイルコンテキスト
      • tsconfig.json
      • コンパイル対象ファイルの設定
    • 宣言空間
    • ファイルモジュール
      • ファイルモジュールの詳細
      • global.d.ts
    • 名前空間
    • 動的インポート
  • Node.js & TypeScriptのプロジェクト作成
  • React & TypeScriptのプロジェクト作成
  • TypeScriptの型システム
    • JavaScriptからの移行ガイド
    • @types パッケージ (DefinitelyTyped)
    • アンビエント宣言(declare)
      • 型定義ファイル
      • グローバル変数の宣言
    • インターフェース
    • Enum
    • lib.d.ts
    • 関数の型
    • 呼び出し可能オブジェクト
    • Type Assertion(型アサーション)
    • Freshness
    • 型ガード
    • リテラル型
    • Readonly
    • ジェネリック型
    • 型推論
    • 型の互換性
    • never
    • 判別可能なUnion型
    • Index signature(インデックス型)
    • 型の移動
    • 例外のハンドリング
    • ミックスイン
  • JSX
    • React
    • React以外のJSX
  • オプション
    • noImplicitAny
    • strictNullChecks
  • TypeScriptのエラー
    • エラーの理解
    • 一般的なエラー
  • NPM
  • テスト
    • Jest
    • Cypress
  • ツール
    • Prettier
    • Husky
    • Changelog
  • その他のヒント
    • String Based Enums
    • Nominal Typing
    • Stateful Functions
    • Bind is Bad
    • Currying
    • Type Instantiation
    • Lazy Object Literal Initialization
    • Classes are Useful
    • Avoid Export Default
    • Limit Property Setters
    • outFile caution
    • JQuery tips
    • static constructors
    • singleton pattern
    • Function parameters
    • Build Toggles
    • Barrel
    • Create Arrays
    • Typesafe Event Emitter
  • スタイルガイド(コーディング規約)
  • TypeScriptコンパイラの内側
    • Program
    • AST
      • TIP: Visit Children
      • TIP: SyntaxKind enum
      • Trivia
    • Scanner
    • Parser
      • Parser Functions
    • Binder
      • Binder Functions
      • Binder Declarations
      • Binder Container
      • Binder SymbolTable
      • Binder Error Reporting
    • Checker
      • Checker Diagnostics
      • Checker Error Reporting
    • Emitter
      • Emitter Functions
      • Emitter SourceMaps
    • Contributing
GitBook提供
このページ内
  • アロー関数(Arrow Functions)
  • Tip:アロー関数の必要性
  • Tip:アロー関数の危険性
  • Tip:thisを使用するライブラリのアロー関数
  • Tip:アロー関数と継承
  • Tip:Quick Object Return

役に立ちましたか?

  1. モダンなJavaScriptの機能

アロー関数

アロー関数(Arrow Functions)

アロー関数は、可愛いらしく_fat arrow_(なぜなら->は細く =>は太い)、または_lambda関数_(他の言語でそう名付けられているため)とも呼ばれます。一般的に利用される機能のひとつは、このアロー関数()=> somethingです。これを使う理由は次の通りです:

  1. functionを何度もタイプしなくて済む

  2. thisの参照をレキシカルスコープで捕捉する

  3. argumentsの参照をレキシカルスコープで捕捉する

関数型言語と比べると、JavaScriptではfunctionを頻繁に打ち込まなければならない傾向があります。アロー関数を使うと、関数をシンプルに作成できます

var inc = (x)=>x+1;

thisはJavaScriptにおいて昔から頭痛の種でした。 ある賢い人は「thisの意味をすぐに忘れるJavaScriptが嫌いだ」と言いました。アロー関数は、それを囲んだコンテキストからthisを捕捉します。純粋なJavaScriptだけで書かれたクラスを使って考えてみましょう:

function Person(age) {
    this.age = age;
    this.growOld = function() {
        this.age++;
    }
}
var person = new Person(1);
setTimeout(person.growOld,1000);

setTimeout(function() { console.log(person.age); },2000); // 1, should have been 2

このコードをブラウザで実行すると、関数内のthisはwindowを参照します。なぜなら、windowがgrowOld関数を実行しているからです。修正方法は、アロー関数を使うことです:

function Person(age) {
    this.age = age;
    this.growOld = () => {
        this.age++;
    }
}
var person = new Person(1);
setTimeout(person.growOld,1000);

setTimeout(function() { console.log(person.age); },2000); // 2

これがうまくいく理由は、アロー関数が、関数本体の外側のthisを捕捉するからです。次のJavaScriptコードは同等の動きをします(TypeScriptを使用しない場合の書き方です)。

function Person(age) {
    this.age = age;
    var _this = this;  // capture this
    this.growOld = function() {
        _this.age++;   // use the captured this
    }
}
var person = new Person(1);
setTimeout(person.growOld,1000);

setTimeout(function() { console.log(person.age); },2000); // 2

TypeScriptを使っているので、はるかに快適な構文で書けます。アロー関数とクラスは、組み合わせて利用できます:

class Person {
    constructor(public age:number) {}
    growOld = () => {
        this.age++;
    }
}
var person = new Person(1);
setTimeout(person.growOld,1000);

setTimeout(function() { console.log(person.age); },2000); // 2

Tip:アロー関数の必要性

簡潔な構文が得られることに加えて、関数を他の何かに呼び出してもらいたい場合も、アロー関数を使うだけで良いのです。本質的には以下の通りです:

var growOld = person.growOld;
// Then later someone else calls it:
growOld();

自分で呼び出す場合は以下のようになります:

person.growOld();

どちらでも、thisは正しいコンテキストになります(この例ではperson)。

Tip:アロー関数の危険性

実は、thisを_呼び出しコンテキストにしたい_場合は_アロー関数を使うべきではありません_。jquery、underscore、mochaのようなライブラリで使用するコールバックのケースです。ドキュメントがthisの機能について言及している場合は、おそらくアロー関数の代わりにfunctionを使うべきでしょう。同様に、あなたがargumentsを使うことを予定している場合は、アロー関数を使用しないでください。

Tip:thisを使用するライブラリのアロー関数

let _self = this;
something.each(function() {
    console.log(_self); // the lexically scoped value
    console.log(this); // the library passed value
});

Tip:アロー関数と継承

クラスのプロパティとしてのアロー関数は、継承において正常に動作します:

class Adder {
    constructor(public a: number) {}
    add = (b: number): number => {
        return this.a + b;
    }
}
class Child extends Adder {
    callAdd(b: number) {
        return this.add(b);
    }
}
// Demo to show it works
const child = new Child(123);
console.log(child.callAdd(123)); // 246

しかし、子クラスで関数をオーバーライドした場合、superキーワードは動作しません。プロパティはthisに行きます。thisは1つしかないので、このような関数は、親クラスの同じ関数を呼び出すことはできません(superはprototypeのメンバだけで動作します)。メソッドを子にオーバーライドする前に、メソッドのコピーを作成することで回避できます。

class Adder {
    constructor(public a: number) {}
    // This function is now safe to pass around
    add = (b: number): number => {
        return this.a + b;
    }
}

class ExtendedAdder extends Adder {
    // Create a copy of parent before creating our own
    private superAdd = this.add;
    // Now create our override
    add = (b: number): number => {
        return this.superAdd(b);
    }
}

Tip:Quick Object Return

時には単純なオブジェクトリテラルを返す関数が必要な場合もあります。しかし、下記のような場合:

// WRONG WAY TO DO IT
var foo = () => {
    bar: 123
};

JavaScriptランタイム(JavaScriptの仕様に原因がある)によって_JavaScript Label_を含む_ブロック_として解釈されます。

この意味がわからなくても心配しないでください。いずれにしろ、"unused label"(未使用のラベル)というTypeScriptのナイスなコンパイラエラーが発生します。Labelは古い(そしてほとんどは使用されていない)JavaScript機能で、現代のGOTO(経験豊富な開発者は悪いものとみなす🌹)として無視して構いません。

()でオブジェクトのリテラルを囲むことで修正できます:

// Correct 🌹
var foo = () => ({
    bar: 123
});
前へClasses Emit次へ残余引数(Restパラメータ)

最終更新 2 年前

役に立ちましたか?

thisを使う多くのライブラリ、例えばjQueryの反復(例: )はthisを使って現在反復中のオブジェクトを渡します。このようなケースにおいて、ライブラリが渡したthisだけでなく周囲のコンテキストにもアクセスしたい場合は、アロー関数が無いときに行うように_selfのような一時変数を使用してください。

このパターンについてのSweetなビデオ🌹
https://api.jquery.com/jquery.each/