javascript メソッドをまとめるオブジェクト、クラス、クロージャについて

メソッドをまとめた何かをつくるにはオブジェクト、クラス、クロージャってヤツらがいる

作成日:2024-02-09, 更新日:2024-02-09

メモ1

こんなやつら

オブジェクトリテラル

let hoge = {};

ただのオブジェクト。各要素に値だけじゃなく関数をセットして使う

クラス

class hoge{}

PHPと同じ感じのクラス

クロージャ

function hoge(){}

ぱっとみ…ただの関数…

メモ2

  • オブジェクトリテラル、クラス、クロージャはすべて継承させることができる
  • オブジェクトリテラルはカプセル化が難しい

どれが優れている…というのはなく、どれを使用するかは要件や開発者の好み次第。

サンプル

オブジェクトリテラル

var exampleObject = (function() {
    var privateVar = '私はプライベートです.';

    function privateFunction() {
        console.log('これはプライベート関数です.');
    }

    return { // return{}内がパブリック要素たち
        publicMethod: function() {
            console.log('これは公開されたメソッドです.');
            privateFunction(); // プライベート関数を使用
        },
        publicVar: privateVar
    };
})();

exampleObject.publicMethod();  // 「これは公開されたメソッドです.」「これはプライベート関数です.」
console.log(exampleObject.publicVar); // 「私はプライベートです.」

クラス

class ExampleClass {
    #privateVar = '私はプライベートです.';

    // 正式な標準になっているか不明(未調査)
    #privateFunction() {
        console.log('これはプライベート関数です.');
    }

    publicMethod() {
        console.log('これは公開されたメソッドです');
        this.#privateFunction(); // プライベートメソッドを使用
    }

    get publicVar() {
        return this.#privateVar;
    }
}

const example = new ExampleClass();
example.publicMethod();  // 「これは公開されたメソッドです.」「これはプライベート関数です.」
console.log(example.publicVar); // 「私はプライベートです.」

クロージャ

function createExample() {
    var privateVar = '私はプライベートです.';

    function privateFunction() {
        console.log('これはプライベート関数です.');
    }

    return {
        publicMethod: function() {
            console.log('これは公開されたメソッドです.');
            privateFunction(); // プライベート関数を内部で使用できます
        },
        publicVar: privateVar // プライベート変数を公開変数として提供
    };
}

var example = createExample();
example.publicMethod(); // 「これは公開されたメソッドです.」「これはプライベート関数です.」
console.log(example.publicVar); // 「私はプライベートです.」

クラスでのthis,eventの受け渡し

bind、アロー関数…記述の種類が多く…わけがわからん

アロー関数をクラスのプロパティとして定義

class zebra {
	// 省略
	aaa = (e) => {
		console.log(this.max);
		console.log(e.target);
		this.bbb();
	}
	add() {
		let div1 = document.createElement('div');
		div1.onclick = this.aaa();

		// ▼これはダメ。「this」が「div2」を指すので「aaa()」が実行されない…
		// let div2 = document.createElement('div');
		// div2.onclick = funciton(e) {
		// 	this.aaa(e);
		// };
	}
}

bind メソッドを使用して this をバインド

class zebra {
	// 省略
	aaa(e) {
		console.log(this.max);
		console.log(e.target);
		this.bbb();
	}
	add() {
		let div1 = document.createElement('div');
		div1.onclick = this.aaa.bind(this);

		let div2 = document.createElement('div');
		div2.onclick = funciton(e) {
			this.aaa(e);
		}.bind(this);
	}
}

イベントハンドラとしてアロー関数を使用する

class zebra {
	// 省略
	aaa(e) {
		console.log(this.max);
		console.log(e.target);
		this.bbb();
	}
	add() {
		let div1 = document.createElement('div');
		div1.onclick = (e) => this.aaa(e);

		let div2 = document.createElement('div');
		div2.onclick = (e) => {
			this.aaa(e);
		};
	}
}

thisを別の変数に格納

class zebra {
	// 省略
	aaa(e) {
		console.log(this.max);
		console.log(e.target);
		this.bbb();
	}
	add() {
		let self = this;

		let div1 = document.createElement('div');
		div1.onclick = self.aaa(e);

		let div2 = document.createElement('div');
		div1.onclick = funciton(e) {
			self.aaa(e);
		}
	}
}

オブジェクトリテラル、クロージャにした場合

クロージャが…いろいろと書き換えるコトができるので…他のいい書き方は存在する

アロー関数をクラスのプロパティとして定義

クラス

class zebra {
	aaa = (e) => {}
	add() {
		let div1 = document.createElement('div');
		div1.onclick = this.aaa;
	}
}

オブジェクトリテラル

const zebra = {
    aaa: (e) => {
        // ここでの this は zebra オブジェクトを参照します
    },
    add: function() {
        let div1 = document.createElement('div');
        div1.onclick = this.aaa;
    }
};

zebra.add();

クロージャ

function createZebra() {
    const aaa = (e) => {
        // ここでの this は createZebra のコンテキストを参照します
    };

    return {
        add: function() {
            let div1 = document.createElement('div');
            div1.onclick = aaa;
        }
    };
}

const zebra = createZebra();
zebra.add();

bind メソッドを使用して this をバインド

クラス

class zebra {
	aaa(e) {}
	add() {
		let div1 = document.createElement('div');
		div1.onclick = this.aaa.bind(this);

		let div2 = document.createElement('div');
		div2.onclick = funciton(e) {
			this.aaa(e);
		}.bind(this);
	}
}

オブジェクトリテラル

const zebraObject = {
    aaa(e) {},
    add() {
        let div1 = document.createElement('div');
        div1.onclick = this.aaa.bind(this);

        let div2 = document.createElement('div');
        div2.onclick = funciton(e) {
            this.aaa(e);
        }.bind(this);
    }
};

クロージャ

function createZebra() {
    function aaa(e) {}

    function add() {
        let div1 = document.createElement('div');
        div1.onclick = aaa;

        let div2 = document.createElement('div');
        div2.onclick = function(e) {
            aaa(e);
        };
    }

    return { add };
}

const zebraClosure = createZebra();

イベントハンドラとしてアロー関数を使用する

クラス

class zebra {
	aaa(e) {}
	add() {
		let div1 = document.createElement('div');
		div1.onclick = (e) => this.aaa;

		let div2 = document.createElement('div');
		div2.onclick = (e) => {
			this.aaa(e);
		};
	}
}

オブジェクトリテラル

const zebra = {
    aaa: function(e) {},
    add: function() {
        let div1 = document.createElement('div');
        div1.onclick = (e) => this.aaa;

        let div2 = document.createElement('div');
        div2.onclick = (e) => {
            this.aaa(e);
        };
    }
};

クロージャ

function createZebra() {
    function aaa(e) {}

    function add() {
        let div1 = document.createElement('div');
        div1.onclick = (e) => this.aaa();

        let div2 = document.createElement('div');
        div2.onclick = (e) => {
            this.aaa();
        };
    }

    return {
        add: add
    };
}

const zebraInstance = new createZebra();
zebraInstance.add();

thisを別の変数に格納

クラス

class zebra {
	aaa(e) {}
	add() {
		let self = this;

		let div1 = document.createElement('div');
		div1.onclick = self.aaa;

		let div2 = document.createElement('div');
		div1.onclick = funciton(e) {
			self.aaa(e);
		}
	}
}

オブジェクトリテラル

const zebra = {
    aaa: function(e) {},
    add: function() {
        let self = this;

        let div1 = document.createElement('div');
        div1.onclick = self.aaa;

        let div2 = document.createElement('div');
        div2.onclick = function(e) {
            self.aaa(e);
        };
    }
};
zebra.add();

クロージャ

function createZebra() {
    function aaa(e) {
        // 何かの処理
    }

    return {
        add: function() {
            let self = { aaa };

            let div1 = document.createElement('div');
            div1.onclick = self.aaa;

            let div2 = document.createElement('div');
            div2.onclick = function(e) {
                self.aaa(e);
            };
        }
    };
}

const zebra = createZebra();
zebra.add();

感想

今までオブジェクトリテラルってのを意図せず使ってきたから…オブジェクトリテラルってのを使い続けていきたい
ただ…使いまわす等、考えるとクラスのほうが無難か?
クロージャは…かなり奥があるというか闇だらけというか…クラスを8割がた理解して使いこなせるようになってから手を出すのが無難かなぁ