LoginSignup
0
0

More than 3 years have passed since last update.

Javascriptのthisどう理解したら

Last updated at Posted at 2020-07-24

jsのthisについて色々なページを見たものを貼り散らかしています。
貼り付けているだけです、すみません。
貼り付けたようなページを見るときは理解できた気分になるのですが、
実際のコードを見ると途端にわからないことが多いです。

今わからないのは、Reactのページにあった
this.handleChange = this.handleChange.bind(this); です。

JSを理解するにはどうしたらいいんだろうか、、

NameForm.js

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

ReactDOM.render(
  <NameForm />,
  document.getElementById('root')
);

jsのthisについて

jsのthis.js
function Test(){
  console.log("f:",this)
}
var obj = {name:"test",Test:test}

var obj = new Test();
obj.test();
console.log("obj:",this);

this

ES5 で bind() メソッド 呼び出し方にかかわらず関数の this の値を設定するために導入され、さらに ES2015 では、独自のthisの関連付けを行わないアロー関数が導入されました (これは包含する字句コンテキストの this の値を保持します)。

これならわかる.js
const test = {
  prop: 42,
  func: function() {
    return this.prop;
  },
};

console.log(test.func());
// expected output: 42

bind関数

  • bind は一度しか機能しない
bind関数.js

function f() {
  return this.a;
}

var g = f.bind({a: 'azerty'});
console.log(g()); // azerty

var h = g.bind({a: 'yoo'}); // bind は一度しか機能しない
console.log(h()); // azerty

var o = {a: 37, f: f, g: g, h: h};
console.log(o.a, o.f(), o.g(), o.h()); // 37,37, azerty, azerty

アロー関数

アロー関数.js
var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject);

関数とthis

  • 関数を呼んだ時の .の前についているオブジェクトを指している。
  • .を省略するとグローバルオブジェクトを参照する

メソッドチェーン

callとappply.js

function test(){
  console.log(this)
}
var obj = {name:"obj"}
test()
test.call(obj)

コンストラクタ

コンストラクタ.js
var obj = new function(){
  this.name = "obj"
  console.log(this)
}


var obj = new function() {
    this.name = "obj"
    name ="obj2"
    console.log(this) // => {name: "obj"}
    console.log(name);
}

thisの4種類のパターン
1:メソッド呼び出しパターン メソッド基準
2:関数呼び出しパターン グローバル
3:コンストラクタ呼び出しパターン
4:apply,call呼び出しパターン

メソッド呼び出しパターン.js
//メソッド呼び出しパターン
var myObject = {
  value: 10,
  show: function() {
    console.log(this.value);
  }
}
myObject.show(); // 10
関数呼び出しパターン.js

function show(){
  console.log(this);
  this.value = 1;
}
show();

関数呼び出しパターン2.js

var myObject = {
  value: 1,
  show: function(){
    console.log(this.value);
    function show(){
      console.log(this.value);
    }
    show();
  }
};
myObject.show();

関数呼び出しパターン3.js
var myObject = {
  value: 1,
  show: function() {
    var self = this;
    console.log(self.value); // 1

    function show() {
      console.log(self.value); // 1
    }
    show();
  }
};
myObject.show();

コンストラクタ呼び出し
- 生成されるインスタンス自身が「this」にsetされる

コンストラクタ.js
function MyObject(value){
  this.value = value;
  this.increment = function(){
    this.value=this.value*4;
  };
}

var myObj = new MyObject(2);
console.log(myObj.value);

myObj.increment();
console.log(myObj.value);

apply, call呼び出しパターン

applycall.js
var myObject = {
  value: 1,
  show: function() {
    console.log(this.value);
  }
};
var yourObject = {
  value: 3
};

myObject.show(); // 1

myObject.show.apply(yourObject); // 3
myObject.show.call(yourObject); // 3

呼び出しパターン2

applycall.js

var myObject = {
  add: function(value1, value2) {
    console.log(this.value + value1 + value2);
  }
};
var yourObject = {
  value: 3
};

myObject.add.apply(yourObject, [2, 10]); // 15
myObject.add.call(yourObject, 2, 10); // 15

クロージャ

コンストラクタの使い方

  • JSではECMAScript 2015(ES6)からクラスを使うことができます。
  • 「new」を付けることで、生成されるインスタンスが「this」にセットされる
constracta.js
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
}

class ChildPerson extends Person {
    get result() {
        this.checkAge();
    }

    checkAge() {
        if(this.age < 20) {
            console.log(this.name + 'は未成年です');
        } else {
            console.log(this.name + 'は成人です');
        }
    }
}

var person = new ChildPerson('太郎', 22);
person.result;

関数とthis
"thisの参照先は主に次の条件によって変化します。

実行コンテキストにおけるthis
コンストラクタにおけるthis
関数とメソッドにおけるthis
Arrow Functionにおけるthis
コンストラクタにおけるthisは、次の章である「クラス」で扱います。 この章ではさまざまな条件でのthisについて扱いますが、thisが実際に使われるのはメソッドにおいてです。 そのため、あらゆる条件下でのthisの動きを覚える必要はありません。"

関数におけるthisの基本的な参照先(暗黙的に関数に渡すthisの値)はベースオブジェクトとなります。 ベースオブジェクトとは「メソッドを呼ぶ際に、そのメソッドのドット演算子またはブラケット演算子のひとつ左にあるオブジェクト」のことを言います。 ベースオブジェクトがない場合のthisはundefinedとなります。

たとえば、fn()のように関数を呼び出したとき、このfn関数呼び出しのベースオブジェクトはないため、thisはundefinedとなります。 一方、obj.method()のようにメソッドを呼び出したとき、このobj.methodメソッド呼び出しのベースオブジェクトはobjオブジェクトとなり、thisはobjとなります。

わかったこと

コンストラクタの中でイベントハンドラにバインドしないといけないらしい
参考
this.メソッド = this.メソッド.bind(this);

0
0
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
0