thisを省略するのやめました
C++ではメンバの参照にthisを省略可能
C++ では、クラスのメンバ関数内では、
Popup::open ( const char* title, const char* mssg )
{
setTitle( title );
setMessage( mssg );
・・・省略・・・
}
こんな風に関数名だけでメンバ関数がコールできます。上のように書けば、Popup::setTitle(), Popup::setMessage() がコールされます。
メンバ関数だけでなくグローバル関数としても setTitle() や setMessage() が定義されていて、グローバル関数の方をコールしたい場合には、
::setTitle( title );
::setMessage( mssg );
と、:: でそれを示す必要があります。
もちろん、メンバ関数をコールする際、
this->setTitle( title );
this->setMessage( mssg );
と、this を付けてメンバ関数であることを明示的に示しても良いわけですが、自分はメンバ関数をコールする際にこの this-> を省略するスタイルを長年続けてきてました。
JavaScriptではまった
JavaScriptではメンバ関数をコールする際、この this が省略不可。
しかしJavaScriptに手を出し始めた頃、C++の癖でちょくちょくこれを省略しちゃってました。
クライアントに納品したJavaScriptのアプリ、「ある条件でウィンドウ毎閉じられてしまう」という指摘を受けまして。
よくよく見てみると、ポップアップをウィンドウを閉じる処理で、
this.close();
と書かなきゃいけないところが単に close() と書いてありまして。
そう、this が省略されているために window.close() が呼ばれてしまってた、というオチです。
省略できるものでも省略しない
この件以来、C++ でも this-> を省略しないで書くようになりました。
DNSが外から引けない
DNSがローカルホストからしか引けない
DNSの設定をして、コマンドラインから host コマンドとか nslookup コマンドを叩いてちゃんと引けてることを確認してものの、なぜか別のホストからだと引けない、なぁんて状況に遭遇したこと、ありますよね?
インターネットを経由して外のネットワークから引けないという場合は、ルータの設定だったりする場合もあるわけですが、同じネットワーク内の他のホストから引けないという場合は、まずこれが原因かと。
named.confをチェック!
named.conf の中に、以下のような記述がないかチェックしてみましょう。
listen-on { 127.0.0.1; };
どのバージョンからだったかは忘れましたが、デフォルトでこんな記述があります。
listen-on は named が listen するIPの指定で、上記の場合、ローカルホストでlistenしろと言っているので、当然ローカルホストからの問い合わせしか答えてくれません。答える以前に、ローカルホスト以外からは接続できません。
解決策は・・・
さっくりと、その行をコメントアウトしましょう。listen-on の指定がなければ、全てのインタフェースでlistenしてくれます。
ちゃんとしたい場合は、正しい外向けのIPを記述しましょう。
C++ でなぜか実行されない行がある
C++ で書いたプログラムで、なぜか実行されない行がある不具合に遭遇し、かなり無駄に時間を費やした経験があります。
// ID-色 対応表
GetColorMap( cmap );
この GetColorMap() がコールされていない、ということが判明するまでイライラしながら結構な時間が経過してるんですが、とにかくそこまでは判明。
この2行の中に、重大なバグが潜んでいるんですね・・・
GetColorMap() の1行前のコメント行が問題なんですね。
最後の「表」の字。
SJISコードではこの「表」、2byte 目が \ のコードと同じ。
すなわち行の最後に \ があるわけで、改行がエスケープされて次の行が同じ行と扱われてしまう。
// ID-色 対応表 GetColorMap( cmap );
と書いたのと同じ。。
わかってみれば当たり前なんですが、これには久々にやられました。
この事件以降、// でコメントを書く場合には、必ず最後に無駄にスペースを入れるようになりました。
JavaScript の bind は超絶便利なんだけど・・・
JavaScript には、「bind」というかなり便利なメソッドがあります。このメソッドを使うことで、this にまつわる良く有る問題をいい感じに解決できます。
thisではまるケース
var User = function (name) {
this.name = name;
}
User.prototype.printName = function() {// このメソッド内で使う this が曲者
alert('My name is ' + this.name);
}
var taro = new User('Taro');
taro.printName(); //「My name is Taro」と表示される
この場合、taro.printName() という形でコールしているので、printName() メソッド内の this は期待通り taro を指します。なので無事「My name is Taro」と表示されます。
ところが下のケースでは・・・
var User = function (name) {
this.name = name;
}
User.prototype.printName = function() {// このメソッド内で使う this が曲者
alert('My name is ' + this.name);
}
var taro = new User('Taro');
setTimeout(taro.printName, 1000);
1秒後に「My name is Taro」が表示されるかと思いきや、これだと「My name is undefined」と表示されてしまいます。
setTimeout に taro.printName を渡した時に、もはや taro の情報は引き渡されません。1 秒後に printName() がコールされる時には、taro と結びついてない状態でコールされます。なので printName() 内で this は taro を指しません!
bind で解決
setTimeout(taro.printName.bind(taro), 1000);
setTimeout() に関数を渡す時、taro.printName.bind(taro) とすることで解決。
1秒後に printName() をコールする際、ここで bind した taro オブジェクトに結び付けてコールしてくれます。この場合期待通り、printName() メソッド内の this.name は taro.name を指しますので、「My name is Taro」と表示されます。
全てのブラウザが対応してるわけではない
ただしこの超便利な bind()、全てのブラウザが対応しているわけではありません。
手元にあった数台のスマホで試してみても、半分くらいはこの bind() が実装されていません。