読者です 読者をやめる 読者になる 読者になる

console.lealog();

@leader22のWeb系に関する勉強めもブログですのだ

0からはじめるJSX Part.2

JavaScript JSX

というわけで、ノンプログラマがこつこつJSXを勉強していくコーナーです。
一応どんなレベルかを書いておくと・・

  • 会社の新入社員研修でJavaを2週間やった+実務で2週間さわった → ほとんど覚えてない。
  • JavaScriptに関しては1年くらい勉強中で、Prototypeとかクラス風な使い方とかを最近かじれてきた程度。
  • PHPに関しても同じくらい。
  • でも全部独学+作りたいサービスに必要なとこだけとかなので偏りあり。
  • Web技術とかそういうのは好きなので、「知識としては」あれこれ知ってる方かと。

そんな私が、プログラミング言語らしいプログラミング言語を覚えるべく、噂のJSXに手を出していきます。

はじめる前に

おそらく正当なやり方は、gitでcloneしてきてコンパイルしてNodeで実行・・なんでしょうけど、それはやりません。
なぜならイマイチよくわかってないから。
VPS借りてるならやれよって話ではあるかと思いますが、オンラインで試せる環境もあることなので、今はそれで良いかと思ってたり。

そのうちやるかもですが、JavaScriptなのでコンパイルしちゃえばローカルでも動くし、ねぇ。

チュートリアルに載ってる

hello.jsxを読み解く

class _Main {
    static function main(args : string[]) : void {
        log "Hello, world!";
    }
}

説明がついてて、

Class _Main has a static member function (a.k.a. a class method) named main, that takes an array of strings and returns nothing. _Main.main(:string[]):void is the entry point of JSX applications that is called when a user invokes an application from command line. JSX, like Java, does not allow top-level statements or functions.

_Mainクラスは静的なmainというメンバーを持ち、それは文字列を引数としてうけとり、何も返しません。
_Main.main(:string[]):voidとは、JSXが動くときに最初に実行されるものです。
Javaと同じく、JSXではトップレベルでの宣言や関数を許していません。

実行すると、consoleに即座にHello, world!されるコードっぽい。

型付言語って

関数や変数やらを宣言するタイミングで、

  • どういう引数をとって
  • どういう結果を返すのか

を一緒に宣言しないといけないっぽい。

そうするからこそ、「型付」されて、安全やったりわかりやすいコードになる・・はず。
微かにJavaでこんなんやった気がする・・・!

お決まりなので、ちゃんと書けってことやと理解します。

staticでvoidなfunction

static function main(args : string[]) : void {
/*
staticはインスタンス作らなくても使えるやつ。
               関数名(引数 : 引数の詳細) 
               		      : 返り値
*/

JavaScriptにはない考え方やと思うので、Javaの情報を調べた結果の理解として。

最初に実行?トップレベル?

これもJavaScriptにはないような・・。
そして日本語でそれらしいのがなかったので、理解が怪しいw
お作法として、コードのトップレベルには、勝手に変数とか関数とか作っちゃダメですっていう決まりの模様。

// 書いたコード・実行させたいコードにおいて

log "Nyaaa";
// いきなり何かするとか

static function main(args : string[]) : void {
    log "Hello, world!";
}
// 関数宣言するとかはダメで

class _Main {
	// hoge...

}
// トップレベル(=一番インデントされてないやつ)は、クラス!

そういう感じでしょうか・・・。

で、中でも "_Main"と名のつくクラスの中身が、実行時に最初に読まれる、と。
というわけでこのクラスの中で、他で準備したやつを呼び出したりする感じとみた。

class Hoge{
	function huga(){
		// 書き方はてきとー...
	}
}

class _Main{
	static function main(args : string[]) : void {
		// Hoge.huga... みたいな?
	}
}

たぶんこんな感じやで・・、たぶん。

とか書いてみて思ったけど、そんな最初に実行されるクラスの名前が決まってるとかありえへんやろーと思う・・ので、今回のサンプルではたまたまこの名前なんやろな。
お作法として、最終的に実行する部分のクラスはこの名前にしときましょうね、みたいなんがあるんかもしらん。

logはconsole.log

自分用のヘルパー関数を勝手に作ることはあるけど、それと似たようなもんかしら。
JSX界では、console.logはlogと同義になっている模様。
おそらくこういうのが他にも沢山あって、コーディングするの楽でしょ!って意味なはず。
それにしてもconsole.logみたく、()がないのはなんでやろう。

クラスベースの言語

サンプルとか読んでてやっとわかったことですが、クラスベースの言語ってこういう意味やったんね。
何を作るにもとりあえずクラスを宣言して、そこに書く。
実行する主体も、メインのクラスとして宣言しておいて、それが実行されて・・みたいな。

ブラウザのJavaScriptメインやと、どうしてもイベント発火待ちになると思います。
ノンプログラマとしては、そこがわかりやすいキッカケやったのにぃ。

素朴な疑問こーなー

というわけで読み解いてみました。
そして貯まった疑問たち。

  • 使ってないのであれば、引数もいらんのじゃ・・?
  • string[ ]の[ ]ってなんですか・・配列?文字の配列で文字列・・?これもお決まり?
  • JSX - Tryでは、勝手なコードを書くとうまく変換してくれない?

例えば最初のhello.jsxで、
"Hello world"じゃなくて、"Goodnight world"とかに変えるだけなら問題なく動くのですが、
TestをTest2とかにすると、コンパイル後の最後のrequireの行の関数名が違っててエラーになっちゃいます。
↑最終的に呼び出す関数名を修正したら動く。
↑というか、Run!ってしたときに実行させるためには、それ用の固定のクラスが必要よね、たぶんエラーというかどうしようもない仕様なんやと自己解決。

  • staticの他にも種類があるらしく、それの違いはなんやろなぁ。

こんな程度で躓くあたりが初心者っぽいなぁと自分でも思いますw

自力で実装してみる

JSXだけじゃなくて、ブラウザを開いたら動くやつを。

Jsx

class _Main {
  static function main() : void {
    log "hello world!";
  }
}

うん、やっぱ引数いらんと思うんですけど・・。

JavaScript

コンパイル後です。

// hello.jsとして保存
var JSX = {};
(function () {
	
	/**
	 * copies the implementations from source interface to target
	 */
	function $__jsx_merge_interface(target, source) {
	  for (var k in source.prototype)
	    if (source.prototype.hasOwnProperty(k))
	      target.prototype[k] = source.prototype[k];
	}
	
	/**
	 * defers the initialization of the property
	 */
	function $__jsx_lazy_init(obj, prop, func) {
	  function reset(obj, prop, value) {
	    Object.defineProperty(obj, prop, {
	      value: value, 
	      enumerable: true,
	      writable: true,
	      configurable: true
	    });
	    return value;
	  }
	
	  Object.defineProperty(obj, prop, {
	    get: function () {
	      return reset(obj, prop, func());
	    },
	    set: function (v) {
	      reset(obj, prop, v);
	    },
	    enumerable: true,
	    configurable: true
	  });
	}
	
	/*
	 * global functions called by JSX as Number.* (renamed so that they do not conflict with local variable names)
	 */
	var $__jsx_parseInt = parseInt;
	var $__jsx_parseFloat = parseFloat;
	var $__jsx_isNaN = isNaN;
	var $__jsx_isFinite = isFinite;
	
	var $__jsx_ObjectToString = Object.prototype.toString;
	var $__jsx_ObjectHasOwnProperty = Object.prototype.hasOwnProperty;
	
	/*
	 * public interface to JSX code
	 */
	JSX.require = function (path) {
	  var m = $__jsx_classMap[path];
	  return m !== undefined ? m : null;
	}
	/**
	 * class _Main extends Object
	 * @constructor
	 */
	function _Main() {
	}
	
	_Main.prototype = new Object;
	/**
	 * @constructor
	 */
	function _Main$() {
	};
	
	_Main$.prototype = new _Main;
	
	/**
	 */
	_Main.main$ = function () {
	  console.log("hello world!");
	};
	
	_Main$main$ = _Main.main$;
	
	var $__jsx_classMap = {
	  "hello.jsx": {
	    _Main: _Main,
	    _Main$: _Main$
	  }
	};
}());

html

<!DOCTYPE HTML>
<html lang="ja-JP">
<head>
	<meta charset="UTF-8">
	<title>Testing JSX!</title>
</head>
<script src="hello.js"></script>
<script>
window.addEventListener("load", function(e) {
  JSX.require('hello.jsx')._Main.main$();
});
</script>
<body></body>
</html>

なんとなーくわかってきた気がします。
しばらくはJSX Tutorial攻めで。

あ、優しく(時に厳しく)ご指導いただける方も探してますので!