LoginSignup
5
4

More than 5 years have passed since last update.

TypeScriptでConstructor外で関数を宣言型か無名関数を代入するかでの実行比較

Last updated at Posted at 2015-08-23

TypeScriptでConstructor外で関数を宣言型か無名関数を代入するかでの実行比較

表題のような記述によってどのようにコンパイル、実行されるのだろうとおもって、
例えば、Class内でメンバメソッドを登録する際に無名関数を代入する場合と、宣言型とで何か違いがあるのかなと思って、ちょっと実験です。

下記func1とfunc2の記述が違います。

module A{
    interface ImoritaA{
        name:string;
    }
    class Aclass implements ImoritaA{
        constructor(public name){
            this.name = "fafa"
        }
        public func1= ()=>{//constructor外、無名関数を代入
        }
        public func2(){ //constructor外、宣言型
        }   
    }
}

この違いはどのようにコンパイルされるのか、、
結果はこう

var A;
(function (A) {
    var Aclass = (function () {
        function Aclass(name) {
            this.name = name;
            this.func1 = function () {//無名関数を代入するとconstructor実行内に記述されたことになる
            };
            this.name = "fafa";
        }
        Aclass.prototype.func2 = function () {//prototypeメソッドとして設定される
        };
        return Aclass;
    })();
})(A || (A = {}));

なるほどですね。。
constructor実行内になるかprototypeに代入されるか、の違いみたいです。

無名関数を代入する方(func1)はコンストラクタ実行外で書いてもそこの中で書く場合とで一緒ってことか?

と思ってさらにこうしてみました。(実行のところは追加しています)

module A{
    export interface ImoritaA{
        name:string;
    }
    export class Aclass implements ImoritaA{
        name:string;
        func1: Function;//追加
        constructor(){
            this.name = "fafa"
            this.func1 = ()=>{//constructor内に移動
                alert('func1です')
            }
        }
        public func2(){
            alert('func2です');
        }
    }
}
//追加記述 実行箇所
var fafa  = new A.Aclass();
console.log(fafa.func1())
console.log(fafa.func2())

コンパイル結果

var A;
(function (A) {
    var Aclass = (function () {
        function Aclass() {
            this.name = "fafa";
            this.func1 = function () {
                alert('func1です');
            };
        }
        Aclass.prototype.func2 = function () {
            alert('func2です');
        };
        return Aclass;
    })();
    A.Aclass = Aclass;
})(A || (A = {}));
var fafa = new A.Aclass();
console.log(fafa.func1());
console.log(fafa.func2());

同じ結果を得られました。
つまり初期化の際にコンストラクタ引数として関数を与えることができるということか。。
下記はさらに実験。
別classの関数を渡してそれを実行しています。

//同じmodule内の別classの関数を呼び出す
module A{
    export interface ImoritaA{
        name:string;
    }
    export class Aclass implements ImoritaA{
        name:string;
        func1: Function;
        fromExternalFunc:Function;//追加
        constructor(fromExternalFunc){
            this.name = "fafa"
            this.fromExternalFunc = fromExternalFunc
        }
        public func2(){
            this.fromExternalFunc()//実行
        }
    }
    export class Bclass{
        static b(){
            alert('eee');
        } 
    }
}

//変更 実行箇所
var bfafa = A.Bclass.b;//staticだから
var fafa  = new A.Aclass(bfafa);
console.log(fafa.func2())//eee

なのでまとめると。。

//略
constructor(
){
//const実行内
}
f = ()=>{}

const実行外で書いたfに無名関数を代入すると、
実行内で

this.f() = function(){}

と書いたことになり、
初期化の際仮引数に関数を渡すつくりにすることができる。
実際のコード

つまり最小のコードで改めてやると

class MoritaB{
    constructor(){
    }
    name = 'fafa';
}

は以下と等価

var MoritaB = (function () {
    function MoritaB() {
        this.name = 'fafa';
    }
    return MoritaB;
})();

ちなみにstaticにするとコメントアウトのとおりです。

class MoritaB{
    constructor(){
    }
    static name = 'fafa';
}
//var MoritaB = (function () {
//    function MoritaB() {
//    }
//    MoritaB.name = 'fafa';
//    return MoritaB;
//})();

なんかconstructor実行外だと勝手に静的メンバみたいなイメージしみこんでたけど
thisがオブジェクトになる。
宣言型はprototypeに代入。

また一つ勉強になりましたー。

ではみなさまよい日曜午前9:40分をーー!(1分だけ有効のあいさつ)

5
4
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
5
4