Paepoi

Paepoi » JavaScript Tips » JavaScript object

JavaScript object

# 最終更新日 2024.01.03

object と function
クラスや構造体のような特別な型はありません、型は全部 function です
JavaScript の function は関数ですがクロージャの仕組みを持っています
その仕組みでクラス(function)とインスタンス(object)を表します
// これがオブジェクトです
let obj = {}
console.log(typeof(obj));
//=> object

// マジです
let suzuki = new Object();
suzuki.bike = 'Katana';
suzuki.car = 'Swift';
console.log(JSON.stringify(suzuki));
//=> {"bike":"Katana","car":"Swift"}


// 配列等も全部オブジェクトです
let arr = [1, 2];
console.log(typeof(arr));
//=> object

// 関数やクラスではこうなります
let Test = function() {}
console.log(typeof(Test));
//=> function

// function を new すればオブジェクトになります
let test = new Test();
console.log(typeof(test));
//=> object

プロトタイプ
JavaScript でクラスのような振舞いをさせる ES5 までの方法
this に定義した変数には object からでないと参照できない
// ベースクラスのようなもの、ES5 表記なのは意図的です
var TestClassBase = function(num) {
    this._num = num;
}
TestClassBase.staticFunc = function() {
    console.log('staticFunc 呼び出し');
}
TestClassBase.prototype.instanceFunc = function() {
    console.log('num は '+ this._num + ' です');
}

// 継承のようなもの
var TestClass = function(num) {
    TestClassBase.call(this, num);
}
TestClass.prototype = Object.create(TestClassBase.prototype);
TestClass.prototype.constructor = TestClass;
// 静的メソッドは無理やり継承
for (var p in TestClassBase) {
    if (TestClass[p] === undefined) {
        TestClass[p] = TestClassBase[p];
    }
}
// 新たな定義
TestClass.prototype.getNum = function() {
    return '百倍すると ' + this._num * 100 + ' です';
}
 
// 直接定義したものはそのまま呼び出す
TestClass.staticFunc();
 
// prototype で定義したものは object 化してから呼び出す
var test = new TestClass(7);
test.instanceFunc();
//tc.staticFunc(); // インスタンス化すると静的関数は呼び出しできない
 
console.log(test.getNum());

クラス
クラスは上記プロトタイプの糖衣構文です、一般的なクラスとは動作が違う場合がある
たとえば static メンバはインスタンス化すると参照できない
// 上記を class で書き直ししたもの、圧倒的に解りやすい
class TestClassBase {
    constructor(num) {
        // コンストラクタ、メンバ変数の初期化等を行う
        // Python 等と同様に既に this は作られている
        this._num = num;
    }
    static staticFunc() {
        console.log('staticFunc 呼び出し');
    }
    instanceFunc() {
        console.log(`num は ${this._num} です`);
    }
}

// サブクラスを作る時は extends を使う
// constructor の引数は親に合わせる必要は無い
class TestClass extends TestClassBase{
    constructor(num) {
        // 継承元の初期化
        super(num);
    }
    getNum() {
        return `百倍すると ${this._num * 100} です`;
    }
}

// static 関数は他言語と同様
TestClass.staticFunc();

// インスタンス化
const tc = new TestClass(7);
tc.instanceFunc();
//tc.staticFunc(); // インスタンス化すると static 関数は呼び出しできない

console.log(tc.getNum());

ゲッター、セッター
関数をプロパティのように呼び出す仕組み、C# でおなじみ
setter で不正な処理を弾いたり何か処理を行ないたい場合に利用する
class TestClass {
    constructor() {
        this._width = 0;
        this._height = 0;
    }
    get width() {
        return this._width;
    }
    set width(num) {
        if (num <= 300) {
            this._width = num;
        } else {
            console.log('300 以上にはできません');
            this._width = 300;
        }
    }
    get height() {
        return this._height;
    }
}

const tc = new TestClass();
tc.width = 400; //=> 300 以上にはできません
console.log(`width は ${tc.width} です`); //=> width は 300 です
tc.height = 400; //=> height に setter は定義されていないのでエラー

メソッド定義の簡略構文
object の仕組みを利用して名前空間のようにクロージャを利用できる
定義はカンマで区切るのを忘れないように
const App = {
    _num: '666',
    func1() {
        return 'Hello';
    },
    func2() {
        return this._num;
    }
}

console.log(App.func1());
console.log(App.func2());

Copyright(C) sasakima-nao All rights reserved 2002 --- 2024.