s 6矢印関数とthis指向

1890 ワード

もっと読む
thisの指向
クラスのアプローチの内部にthisが含まれている場合は、クラスのデフォルトのインスタンスを指します.しかし、この方法を単独で使うと、エラーが発生する可能性がありますので、十分に注意してください.

class Logger {
  printName(name = 'there') {
    this.print(`Hello ${name}`);
  }

  print(text) {
    console.log(text);
  }
}

const logger = new Logger();
const { printName } = logger;
printName(); // TypeError: Cannot read property 'print' of undefined
上記のコードでは、printNameメソッドのthisは、デフォルトではLoggarクラスのインスタンスを指します.しかし、この方法を抽出して単独で使用すると、thisはこの方法が実行されている環境を指します(class内部は厳格なモードですので、thisが実際にundefinedを指しています).
比較的簡単な解決方法としては、構造方法でthisを結合すると、print方法が見つけられなくなります.

class Logger {
  constructor() {
    this.printName = this.printName.bind(this);
  }

  // ...
}
もう一つの解決法は矢印関数を使用します.

class Obj {
  constructor() {
    this.getThis = () => this;
  }
}

const myObj = new Obj();
myObj.getThis() === myObj // true
矢印関数内部のthisは、常に定義されたオブジェクトを指します.上のコードでは、矢印関数は構造関数の内部にあり、その定義が有効になると、構造関数が実行される時です.この場合、矢印関数がある動作環境は、必ずインスタンスオブジェクトになりますので、thisは常にインスタンスオブジェクトを指します.
もう一つの解決方法はProxyを使って、方法を取る時、自動的にthisを結びつけることです.
function selfish (target) {
  const cache = new WeakMap();
  const handler = {
    get (target, key) {
      const value = Reflect.get(target, key);
      if (typeof value !== 'function') {
        return value;
      }
      if (!cache.has(value)) {
        cache.set(value, value.bind(target));
      }
      return cache.get(value);
    }
  };
  const proxy = new Proxy(target, handler);
  return proxy;
}

const logger = selfish(new Logger());