問題
こういうことできないだろうなー、と思って書いてたら、できてびっくりしたのです
var Thief = function(name) { this.name = name; }; Thief.prototype.commitTheft = function(){ console.log("( ^ω^).。oO( 俺の名前は「" + this.name + "」、今から盗みに入るぜ!!"); }; Thief.prototype.disguise = function(anotherName) { var self = this; setTimeout(function(){ // thisをコピーしてるだけだから // thisのnameは変わらないと思うのだが... self.name = anotherName; }, 0); }; Thief.prototype.afterAll = function() { var self = this; setTimeout(function(){ console.log("(´-`).。oO( 今回の盗みは簡単だった"); console.log("(´-`).。oO( 名前を「" + self.name + "」に偽るだけで"); console.log("( ^ω^).。oO( 逃げおおせたぜ!"); }, 0); }; // main (function(){ var lupinTheThird = new Thief("ルパン三世"); lupinTheThird.commitTheft(); lupinTheThird.disguise("銭形刑事"); lupinTheThird.afterAll(); })();
けっか
% node main.js ( ^ω^).。oO( 俺の名前は「ルパン三世」、今から盗みに入るぜ!! (´-`).。oO( 今回の盗みは簡単だった (´-`).。oO( 名前を「銭形刑事」に偽るだけで ( ^ω^).。oO( 逃げおおせたぜ!
あらま
JavaScriptのselfって
今までただのオブジェクトで、thisをどっかに退避させて代わりにに書くならじゃーまーselfにしますかー、っていう程度のものだと思ってたの。
ためしに、thisをhogeオブジェクトに退避させて同じことをしてみると、
--- main.js 2013-12-30 21:30:04.000000000 +0900 +++ main2.js 2013-12-30 21:29:45.000000000 +0900 @@ -5,17 +5,17 @@ console.log("( ^ω^).。oO( 俺の名前は「" + this.name + "」、今から盗みに入るぜ!!"); }; Thief.prototype.disguise = function(anotherName) { - var self = this; + var hoge = this; setTimeout(function(){ // thisをコピーしてるだけだから、thisのnameは変わらないと思うのだが... - self.name = anotherName; + hoge.name = anotherName; }, 0); }; Thief.prototype.afterAll = function() { - var self = this; + var hoge = this; setTimeout(function(){ console.log("(´-`).。oO( 今回の盗みは簡単だった"); - console.log("(´-`).。oO( 名前を「" + self.name + "」に偽るだけで"); + console.log("(´-`).。oO( 名前を「" + hoge.name + "」に偽るだけで"); console.log("( ^ω^).。oO( 逃げおおせたぜ!"); }, 0); };
% node main2.js ( ^ω^).。oO( 俺の名前は「ルパン三世」、今から盗みに入るぜ!! (´-`).。oO( 今回の盗みは簡単だった (´-`).。oO( 名前を「銭形刑事」に偽るだけで ( ^ω^).。oO( 逃げおおせたぜ!
ありゃ?ふつうにselfと同じ挙動だし、できとるやん
どうやら
selfとかいうこと関係なく、「JavaScriptのオブジェクトは参照渡しである」という根本的な仕様だったみたいだ。
- javascriptでthisと戯れる — ありえるえりあ
- JavaScript のオブジェクトは参照渡しで代入される
- JavaScript 参照渡しと値渡しの罠 vol.1 - 真夜中のプログラミングTips
- 公式referenceみたいなの見つかんなかったorz
まとめ
- JavaScriptのオブジェクトの代入は参照渡しのようなので、コールバック直前でthisをself(ないし任意のオブジェクト)に退避させてそのプロパティを上書きすると、thisのプロパティも改変される
ということか(;^ω^)
DRY