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

DRYな備忘録

Don't Repeat Yourself.

JavaScriptのselfってthisのディープコピーじゃなくて参照なのかもしかして【this】【JavaScript】

javascript

問題

こういうことできないだろうなー、と思って書いてたら、できてびっくりしたのです

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( 逃げおおせたぜ!

あらま

f:id:otiai10:20131230212249j:plain

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をself(ないし任意のオブジェクト)に退避させてそのプロパティを上書きすると、thisのプロパティも改変される

ということか(;^ω^)

DRY