Dartを使ってみる
Dart
- ECMAの標準規格になったらしい
- jsにcompile可能な汎用言語らしい
- javaとjavascriptのいいとこ取りらしい
ってことで試してみる
イメージ
- DartEditorなるものがあるけど、とりあえずvim使ってみる
- Botでも書いてみるかー?
- for web appsな雰囲気あるけど、現状はWEB向きってだけで別にCLIツールでも良さそう
- とりあえず感触を知るところを目的に、いきあたりばったりで。
installation
core
homebrewでdartの1.6.0がインストールできるらしいのでいれてみる。
$ brew update $ brew upgrade $ brew install dart
versionを見てみる。
Dart VM version: 1.6.0 (Tue Aug 26 22:30:33 2014) on "macos_x64"
- dart
- dart2js
- dartanalyzer
- dartfmt
今回はdart-editorいれなかったけど、brew install dart-editor
でいけるっぽい。
vim-plugin
dart-vim-pluginがある。
NeoBundleの設定に追加してインストール。
NeoBundle 'dart-lang/dart-vim-plugin'
...とおもったら、デフォルトだとfiletype認識してくれないので以下を追加。
au BufNewFile,BufRead *.dart set filetype=dart
hello world
hello-world.dart
void main() { print("hello world!"); }
$ dart hello-world.dart hello world
できた。簡単。 ・・・ついでにdart2jsも試してみる。
$ dart2js hello-world.dart Dart file (hello-world.dart) compiled to JavaScript: out.js
out.jsに吐出されたらしいのでひらいてみ・・・・・・・・・
・・・・
・・・・
・・・・そっ閉じ。
next()
とりあえずインストールはしたのでこれからコツコツ勉強してこう。
実際、今まで培ったnpmライブラリの知見を活かせない(dartはdart専用のライブラリを使う)のは大分未練がある。 でもシンタックス的には結構良さそうにも見えるので、今後に期待を込めて続けられたらいいのかなって雰囲気。
npmライブラリを利用できるか、node上でdartをエミュレートできると移行と実験しやすいんだけど・・・。
まあ、ともあれ勉強っすな
CasperJSを拡張したライブラリをローカルに置こうとして苦戦した記録
CasperJSを使っていて大変苦労したのでその記録。
やりたかったコト
CasperJSを継承した独自拡張のライブラリを複数のファイルでrequireして個別にプログラムを実行したかった。
grunt-casperのようなライブラリをから使う場合と、単体のファイルをcasperjs
コマンドで実行する二通りの用途を想定していた。
継承
継承自体は簡単に可能。 coffee-scriptを使っているならなおのこと。
Casper = require("casper").Casepr class MyCasper extends Casper start: -> console.log "start my casper!" super
外部ファイルとしてrequireする
辛かったのはここから。
上記のクラスをmodule.exports
で吐き出し、他のファイルからrequire
で参照しようとした。
"use strict" Casper = require("casper").Casper class MyCasper extends Casper start: -> console.log "start my casper!!" super module.exports = MyCasper
"use strict" MyCasper = require("my-casper.coffee") casper = new Casper() casper.start "https://www.google.com/", -> @echo "open #{ @getTitle() }" casper.run()
上記のようなサンプルコードを用意して、コマンドを叩く。
vimshell% casperjs runner.coffee Error: Cannot find module 'casper' phantomjs://bootstrap.js:289 phantomjs://bootstrap.js:254 in require /home/mizuki/project/casper-sample/my-casper.coffee:8 /home/mizuki/project/casper-sample/my-casper.coffee:29 /home/mizuki/project/casper-sample/my-casper.coffee:30 ReferenceError: Can't find variable: Casper runner.coffee:8 runner.coffee:16
Cannot find module 'casper'
requireしようととしているcasperが見つからない。
bootstrap.js:289
このファイルをまず見に行く。
情報がほとんど無いので、エスパーで回答すると、
- casperjs/bootstrap.js at 4f105a91a0e1d48826d124b2be3627276986fcb9 · n1k0/casperjs · GitHub
casperjs/bootstrap.js at 4f105a91a0e1d48826d124b2be3627276986fcb9 · n1k0/casperjs · GitHub
どう見てもずれている・・・
ここからPrintDebugタイムに突入し以下の情報を仕入れた。
- PhantomJSの
require
にpatchを当てている - casperなる(CasperJSに関連した)node_modulesはなく、
patchedRequire
の中でCasperJSのmodules
のディレクトリを見に行くようにになっている
patchedRequire
のコード
casperjs/bootstrap.js at 4f105a91a0e1d48826d124b2be3627276986fcb9 · n1k0/casperjs · GitHub
その中で呼ばれているcasperBuiltinPath
メソッドがcasperの内部のmodulesさんからcasper
を探してきている。
function casperBuiltinPath(path) { return resolveFile(path, fs.pathJoin(phantom.casperPath, 'modules')); }
さて、ここらへんにprintデバッグのコードを埋め込むわけだが端的に結論を行ってしまうと、 呼 ば れ て い な いのだ。
require先のライブラリの中ではcasperjsのpatchが当たらないらしい。 どういう仕組でそうなっているのかは、PhantomJSも含めて周辺コードを追跡しないといけないので、ひとまずはこの仕組を諦めることにした。
いずれリベンジしたいところである。
余談
ローカルパスの検索
phantom.casperScriptBaseDir
もしくはfs.workingDirectory
を基準にrequire
に指定したパスを走査する。
function localModulePath(path) { return resolveFile(path, phantom.casperScriptBaseDir || fs.workingDirectory); }
casperScriptBaseDirはどこで設定されるのかというと、
- casperjs/bootstrap.js at 4f105a91a0e1d48826d124b2be3627276986fcb9 · n1k0/casperjs · GitHub
- casperjs/bootstrap.js at 4f105a91a0e1d48826d124b2be3627276986fcb9 · n1k0/casperjs · GitHub
コマンドラインのtest
サブコマンドを除く第一パラメーターである。
すなわち、下記のrunner.coffee
のディレクトリである。
vimshell% casperjs runner.coffee
今回示した例ならさほど問題はないが、src/runner.coffee
の様なケースだと、若干面倒になる。
これはnodeJSも同様だが、相対パスと実行ディレクトリを意識しなくてはならない。
casperScriptBaseDir
を書き換えることでこの問題を回避することもできるがオススメしない。
Nodeであれば、NODE_PATHを追加することで、そのディレクトリをnode_modulesの走査対象とするが、CasperJSについてはそこまで確認していない。
この辺りのソースを追っていけばヒントは得られそう。 casperjs/bootstrap.js at 4f105a91a0e1d48826d124b2be3627276986fcb9 · n1k0/casperjs · GitHub
ともあれ、非常に苦戦したので、とりあえずその調査の記録だった。
YAPC::Asia 2014に参加してきました #yapcasia
YAPC::Asiaとは
8/29, 8/30に開催された、世界最大規模のプログラミングカンファレンスです。 Perl界隈のエンジニアからPerlは関係ないけど、プログラミングが好きな人が集まる年に一度のエンジニアの祭典!
この記事は
わたしく@mizuki_rの個人的な見解をだらだら述べる記事でございます。 なお、藤沢にある某メイドバーで執筆しているなう。何してんだ、ほんとなにしてるんだ僕。
全体の振り返り
最後のkeynoteのtypesterさんのトークは正直胸に刺さった。 なんだろう、まだうまい言葉に落とせていないような感動具合。 本当にいいトークだった。
通して、自分の立ち回りや今後のキャリアプランとかを改めて考えさせられるスピリチュアルなトークが多かった印象。 同期が二人発表しているのを見て、やっぱりトークしたかったなぁと思う反面 参加してよかったYAPC! 大好きYAPC! スタッフの皆さんお疲れ様でした!
@yusukebe さん大変だとおっしゃっていたけどぜひとも来年も開催を、そして次こそスピーカーとして参加したいw
あ、あと落選したトーク、どこかで話せる機会を作りたいな。
8/29日の振り返り
僕が参加したトークは以下。 真面目なまとめや評価に関しては、技評さんや他のすばらしいエンジニアのブログを参考にしてくれといいな。
あと、量が多いので個人的に興味のある記事だけピックアップしちゃう。
- インフラエンジニア(狭義)は死んだ
- Go For Perl Mongers
- お待たせしました。Perl で BDD を簡単に実践する最高にクールなフレームワークができました
- Perl::Lint - Yet Another Perl Source Code Linter
- WHERE狙いのキー、ORDER BY狙いのキー
- Mojoliciousを使ったwebアプリケーション開発 実践編
- Java For Perl Mongers
インフラエンジニア(狭義)は死んだ
WEBのインフラ系は、物理面を意識することも減ったし、便利なツールも増えてきている。 アプリが動いているのもソフトウェアだし、便利なツールもプログラミングできないと使いこなせない場合も増えている。 この先、プログラミングできないインフラエンジニアは死にそう。
そんな状況で、プログラミングから逃げていた(逃げていたとはもう今は思えない)studio3104氏がどうプログラミングと向き合ってきたのかっていうお話。
「インフラエンジニア」っていう言葉は「プログラミングできない」「プログラミングができなくてもいい」みたいな認識があって、 「インフラエンジニア」ってなのることでそのことを許容しているのではないか? 自称は自意識に影響を与えるというメッセージはすごく僕に刺さった。
僕自身フロントエンドエンジニアという自称の中で、いくつかの責務から目をそらしていた節がある。
与えられた役割、動ける範囲を改めて見直して自称ではなく、自分として何ができるかを改めて考えてみようと思った。
すごい意識の高いトークで一発目からしびれました。
お待たせしました。PerlでBDDを簡単に以下略
tokuhiromさんが書いてきたTest系Moduleの振り返りと、perl6並に夢の詰まったTest::Builder2の開発停止に伴う、じゃあぼくらはどうすればいいんだに対する回答。
それがTest::Kantan 最近のテストライブラリから、言うまでもなく後方互換を保ちつつテストの集計を刷新したunicode文字使ったり色つければウケがいいというフレームワーク。
subtestはテストのコンテキストがわかりにくく、JavaScriptでBDDを主体としたSpecによるテストを行っていた最近の僕としては、 より可用性のあるライブラリっぽい気配がしてもう胸がたかなる。
なお、後輩が試した話によるとサンプルそのままだと動かなくて、describeバグってるぽい? 余裕見て検証したいところである。
Perl::Lint
バグとなりそうな危ういコードを指摘してメンテナビリティの高いコードを推奨しつつレビューの手間を省くツール、それがソースコードリンター。 PBPのポリシーを実装したperlcriticは遅いので、もっと早いのを作りました、というトーク。
Perlの静的解析の手法と、Perl::Lintの使い方の説明をしつつ、いやぁモダンな名前空間だなぁと思っていた。 perlcriticnのカスタマイズはなかなか職人芸な気がしていて手が出しにくい。しかも時間かかるから常にテストと一緒に走らせるには重い。
そんな状況の打開策を提案してくれるモジュールのよう。
独自ポリシーの定義をサポートしつつ、perlcriticのまんまのポリシーを定義している。
独自ポリシーの定義をサポートしつつ、perlcriticのまんまのポリシーを定義している。 もちろん、簡単なポリシーなら簡単にかけるが、難しいポリシーをかくのは難しいというまあそうだよねってところだけど、今後に期待。
なお現在ラスボスのようなポリシーを実装してくれるコントリビューターを募集しているそう。 われこそわという方はぜひ。
僕はjshintを読んで挫折しました。
8/30の振り返り
- オープンソースの開発現場 - Perl 5.20 のSubroutine Signaturesが来るまでの奮闘の軌跡
- 半端なPHPDisでPHPerに陰で笑われないためのPerl Monger向け最新PHP事情(5.6対応)
- ほんとにあったスキーマの話 「ソーシャルゲーム」
- Perlあるある
- Mobile Application Development for Perl Mongers
- そんなにビッグでもないデータ処理手法の話
オープンソースの開発現場
perl 5.20で入ったsignaturesにまつわる議論についてのお話。 個人的にはベストトークショーになってほしいくらいいい話だった。
signaturesの実装を提案し議論を醸したMartini氏の奮戦とその立ち回り、p5pという民主主義のメリット・デメリットはとても興味深いものだった。 perl5は多様な人が居て、多様な意見がある。
そのなかで自分の目指すべきところを正確に見据え、その優先順位を守って、時には受け止め、時には受け流しうまいこと立ちまわることがOSSにおいて大事なのだと感じた。 いろんな人達の日々の努力よって僕らは支えられ、いまこうしてコードを書いているのだと改めて感謝したトークだった。
ちなみにはやくsingaturesを使うの楽しみにしてるぜ!!!
半端なPHPDisで以下略
皆まで言うな、今回のベストトークショーである。 perlのカンファレンスでPHPのトークがベストトークショーともう伝説だよねこれwwww
語るまでもない、PHPのもつ闇としかしその闇と戦うPHPerの強いメンタルを垣間見た。 元PHPerとしては、PHPの変化にちょっと興味をそそられ、たまには弄りたいなと思った。
でもやっぱりPHPはいいかなwwww
Perlあるある
豪華メンツを集めた対談みたいな、Perl初学者向けのトーク。 名を轟かすPerlMongersの赤裸々な素顔に迫るトークだった。
いろいろ名言いただきましたけど、ちょっと個々では割愛。 多くて・・・。
ただ、 「コードを書くのに許可はいらない」 「コードも作文も同じ。読まれて意味の分からないコードは書かない」 「基礎が大事」 「Done is better than perfect」 心に刻みたい。
追記
WindowsでWebアプリ開発
何やるかを考える。
前提
学んでもらうこと
開発環境構築
開発OS準備
以下のものを用意してもらう。
準備
- https://www.virtualbox.org/wiki/Downloads からVirtualBoxのexeファイルをダウンロードして、インストールする。
- https://www.ubuntulinux.jp/download/ja-remix-vhd から Ubuntu 12.4 のイメージディスクをダウンロードする。
- ダウンロードした圧縮ファイルを解凍し、中のvhdファイルを
C:\Users\$USER\.VirtualBox
のディレクトリに移動する。
イメージの作成
- VirtualBoxを起動
- 新規(N)から作成。名前を
ubuntu
(とりあえず)、タイプをLinux
、バージョンをUbuntu(32bit)
とそれぞれ設定して次へ - メモリ割り当ての確認があるがひとまずデフォルトのままでよい。
- ハードドライブの割り当てもデフォルトですすめる。
- ドライブの割り当てはすでにあるドライブを選択し、先ほどダウンロードしたvhdファイルを選択する。
- 設定完了。
開発OSのインストール
- ホーム画面から、
ubuntu
のイメージを選択して起動する。 - 初回だとCreating process for virtual machine "ubuntu"...というメッセージがでて初期化処理が走るためしばらく時間がかかるので注意。
- あとはノリで進める FIXME
- ひと通りインストールが終わると、ログインを要求されるのでログインする
- ログインできたら完了。
インストール後にやる設定
terminal
を開くsudo apt-get update && sudo apt-get upgrade
開発ツールのインストール
ssh接続を可能にする
vmのubuntuにminttyやputtyからアクセスできるようにする。
Ubuntu側での作業
sudo apt-get install openssh-server
Windows側での作業
1. VirtualBoxの設定を開く
2. ネットワーク
3. ポートフォワーディング
4. 新規ルールを追加
5. ルール名(ex: SSH)、ホストポート(ex: 50022)、ゲストポート(22)を追加
6. ssh user@localhost -p 50022
をputty等でsshできるか確認
7. 鍵通す。
zshのインストール
shellは慣れてるヤツで。
$ curl -L -O http://sourceforge.net/projects/zsh/files/zsh/5.0.5/zsh-5.0.5.tar.bz2 $ tar xjvf zsh-5.0.5.tar.bz2 $ cd zsh-5.0.5/ $ ./configure --enable-multibyte $ make $ sudo make install
login shellの変更。
$ which zsh /usr/local/bin/zsh $ cat /etc/shells # /etc/shells: valid login shells /bin/sh /bin/dash /bin/bash /bin/rbash # echo `which zsh` >> /etc/shells $ chsh パスワード: 新しい値を入力してください。標準設定値を使うならリターンを押してください ログインシェル [/bin/zsh]: /usr/local/bin/zsh $ exit
gitのインストール
https://code.google.com/p/git-core/downloads/list から最新版を取得。
curl -L -O 'https://git-core.googlecode.com/files/git-1.9.0.tar.gz' tar xzvf git-1.9.0.tar.gz cd git-1.9.0 ./configure make sudo make install
依存系のライブラリをインストール
sudo apt-get install zlib1g-dev sudo apt-get install tcl sudo apt-get install gettext
vimのインストール
curl -L -O ftp://ftp.vim.org/pub/vim/unix/vim-7.4.tar.bz2 tar xjvf vim-7.4.tar.bz2 cd vim74 ./configure --enable-multibyte --enable-luainterp --enable-perlinterp --enable-pythoninterp --enable-rubyinterp make sudo make install
to be continued
node-scheduleという予定を登録して実行するnpmライブラリの紹介
node.jsを使っていて出会った、使い勝手の良さそうなライブラリ(俺基準)を紹介していくシリーズを初めてみました。
node-schedule
https://www.npmjs.org/package/node-schedule
指定時間に登録したタスクを実行してくれるライブラリです。 Dateオブジェクト、日時指定、時刻指定、CRON形式での指定等に対応し、非常に使い勝手が良いです。
installation
npm install
usage
scheduleJob
メソッドを呼び出すことでタスクが登録されます。
第一引数に実行タイミング、第二引数にジョブ名(省略可)、第三引数に実行したいタスクを登録します。 返り値はJobオブジェクトです。
var schedule = require("node-schedule"); var job = schedule.scheduleJob(timing, name, fn);
JobオブジェクトはEventEmitterを利用しており、いくつかのフックポイントが提供されています。
- scheduled: タスクの登録時
- run: タスク実行
- cahceled: 予定のキャンセル時
job.on("scheduled", function () { console.log(this.name + "の予定が登録されました"); }); job.on("run", function () { console.log(this.name + "の予定が実行されました"); }); job.on("canceled", function () { console.log(this.name + "の予定がキャンセルされました"); });
Dateオブジェクトを使う場合
下記は2014/07/05 22:30:00
に処理を実行する場合の例です。
var job = schedule.scheduleJob(new Date(2014, 07, 05, 22, 30, 0), function () { console.log("登録されたジョブの実行"); });
日時を指定する場合
以下の項目をオブジェクトで定義します。
- year
- month
- day
- dayOfWeek
- hour
- minute
- second
下記は毎日18:30
に処理を実行する場合の例です。
var job = schedule.scheduleJob({ hour : 18 minute: 30 }, function () { console.log("実行"); });
CRON形式
下記は毎日18:30
に処理を実行する場合の例です。
-
による範囲指定は可能ですが、/
による指定はできないようです。(たぶん)
var job = schedule.scheduleJob('30 18 * * *', function () { console.log("実行"); });
まとめ
node-scheduleはご覧の通り、特定日時や特定時間での繰り返し処理に向いています。 記法が多岐に渡り、様々なタイマー処理に適応できます。
ちなみに僕はIRCBotでミーティングや予定のリマインドに利用しています。 ぜひ使ってみてください
AngularJSのfactoryとserviceを読み解く(後編)
前編: ngularJSのfactoryとserviceを読み解く(前編)
前回のAngulaJS!(なんちゃらライブ的な) factoryやserviceといったAngularJSの機能をドキュメントを読んだりぐーぐる先生に聞いたりしてもまったくさっぱりよくわからなかったのでAngularJSのコードを追ってみた。
factoryは初期化処理をInjectorで一度だけ実行してその結果をAngularJSのcacheFactoryを使ってキャッシュしているところまではわかった。
しかし、serviceはよくわからなかった。 よくわからないので振り返りから。
.service(name, fn)
- serviceが呼ばれる
- $injector.instantiateにfnが渡される
- $injector.instantiateで別のクラス(仮にAとする)を作成してprototypeを継承する
- $injector.instantiateでクラスAのインスタンスを生成して$injector.invokeにserviceに指定したfnと共に渡す
- $injector.invokeでDIに指定したDependenciesを解析、取得
- $injector.invokeで、引数をdependenciesに、コンテキストをクラスAのインスタンスにしていしてfnを実行する
- $injector.invokeの返り値がobjectまたはfunctionであればそれをfactoryに渡す
- $injector.invokeの返り値がobjectでもfunctionでもなければクラスAのインスタンスをfactoryに渡す
つまり、こういうことだ!
// serviceに登録するfunction(コンストラクタ) var User = function (options) { this.name = options.name || null; this.age = options.age || null; this.set = function (column, value) { this[column] = value; }; this.get = function (column) { return this[column]; }; }; // $injector.instantiate var Constructor= function () {}; Constructor.prototype = User.prototype; var instance = new Constructor(); // $injector.invoke User.apply(instance, [{name: "tarou", age: 10}]); var user = instance;
・・・実にわかりにくい。
気をつけなければならないのは、serviceの第二引数は初期化コールバック関数ではなく、クラスのコンストラクタであること。
factoryとおんなじ用に使うのは不適切で、angularとは別に定義したクラスを指定する(app.service("name", ["$rootScope", MyServiceClass])
のように)か、コンストラクタで完結するクラスを定義すべきだ。
var User = function (options) { this.name = options.name || null; this.age = options.age || null; this.set = function (column, value) { this[column] = value; }; this.get = function (column) { return this[column]; }; }; app.service('user', [User]);
app.service('user', [function () { this.name = options.name || null; this.age = options.age || null; this.set = function (column, value) { this[column] = value; }; this.get = function (column) { return this[column]; }; }]);
serviceはどういう時に使うべき?
factoryとの違いとして、serviceはインスタンスの生成を保証し、かつ同一の名前空間で他のインスタンスは作られない。
デザインパターンで言うところのSingletonであり、アプリケーション内で整合性を管理する用途にもちいられるのだと想定できる。
たとえば、複数のController間で一つのリソースを管理したい場合などがそれに該当すると思われる。
下手に$rootScopeに値を入れたりするよりは固く実装できるのではないだろうか。
まとめ
serviceはSingletonなので、それなりの扱いを用意しよう。 serviceメソッドの第二引数はコンストラクタなのでそれを念頭に置いて利用しよう
AngularJSのfactoryとserviceを読み解く(前編)
AngularJSのfactory
とservice
がどうにも覚えられないのでまとめてみた。
まとめ
- factoryはobjectをキャッシュしておく
- serviceはインスタンス化してキャッシュしておく
- providerの謎が深まった
factory
providerにfunctionらしきものを渡している。
$get
はInjectorに指定されたときに一度だけ呼ばれる。
function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }
https://github.com/angular/angular.js/blob/master/src/auto/injector.js#L666
ここまでだとまだ実行されない。
var app = angular.module('app', ['ngResource']).factory('User', function ($resource) { return $resource('/api/user/:id', {id: "@id"}, {}); });
ここで実行され、以降の呼び出しはreturn $resource('/api/user/:id', {id: "@id"}, {});
の評価結果がキャッシュされたヤツが呼び出される。
app.controller("UserCtrl", function (User) { $scope.user = User.$get(id: 1); });
service
serviceに指定された無名関数はconstructor
という名で$injector.instantiate
の引数に渡され、その処理をfactoryへと渡している。
function service(name, constructor) { return factory(name, ['$injector', function($injector) { return $injector.instantiate(constructor); }]); } function value(name, val) { return factory(name, valueFn(val)); } function constant(name, value) { assertNotHasOwnProperty(name, 'constant'); providerCache[name] = value; instanceCache[name] = value; }
https://github.com/angular/angular.js/blob/master/src/auto/injector.js#L668-L680
$injector.instantiate
は与えられた引数を、あたらにConstructor
クラスが作られ、serviceに登録した関数のprototypeを継承させいる。
なぜArrayの場合は末尾を取り出しているのかはよくわかってない。
['$rootScope', function () { ... }]
的なアレの為に、Arrayの判定してる。
Constructor
クラスをインスタンス化し、invoke(省略)に渡す。
その返り値がObjectまたはFunctionであればそのままをfactoryにわたすが、どちらでもない場合はConstructor
のインスタンスをfactoryに渡している。
function instantiate(Type, locals, serviceName) { var Constructor = function() {}, instance, returnedValue; // Check if Type is annotated and use just the given function at n-1 as parameter // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]); Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype; instance = new Constructor(); returnedValue = invoke(Type, instance, locals, serviceName); return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance; }
https://github.com/angular/angular.js/blob/master/src/auto/injector.js#L804-L815
なお、invokeでは(重要なところだけを挙げれば)Constructor
クラスのインスタンスをコンテキストとしてserviceで指定した関数を実行しその結果を返しているだけである。
function invoke(fn, self, locals, serviceName){ if (typeof locals === 'string') { serviceName = locals; locals = null; } var args = [], $inject = annotate(fn, strictDi, serviceName), length, i, key; for(i = 0, length = $inject.length; i < length; i++) { key = $inject[i]; if (typeof key !== 'string') { throw $injectorMinErr('itkn', 'Incorrect injection token! Expected service name as string, got {0}', key); } args.push( locals && locals.hasOwnProperty(key) ? locals[key] : getService(key) ); } if (!fn.$inject) { // this means that we must be an array. fn = fn[length]; } // http://jsperf.com/angularjs-invoke-apply-vs-switch // #5388 return fn.apply(self, args); }
https://github.com/angular/angular.js/blob/master/src/auto/injector.js#L801
ここまで追ってみたけどよくわからないので、続きは明日。
Constructor
で空のクラスをprototypeだけ継承し、インスタンス化する。そののちにinvokによってDependenciesを引数としてserviceで指定したfunctionに渡すことで、DIとしての動きを作っているっぽい。
どう使うのかはまだ曖昧だけど、輪郭が見えてきた。