Help us understand the problem. What is going on with this article?

[JavaScript]小技的な何か

More than 5 years have passed since last update.

自己定義関数

var devour = function(target){
    //1回目の実行のみ実行される
    console.log('ゲルトが無残な姿で発見されました。');

    //devourを再定義
    devour = function(target){
        //2回目以降実行される
        console.log(target + 'が無残な姿で発見されました。');
    }
}
devour('ヨアヒム');   //ゲルト
devour('リーザ');     //リーザ
devour('ペーター');   //ペーター

 関数のなかで実行した関数を再定義すると、初回のみ実行したい処理をひとつの関数のなかで分離できる。

 また、再定義後のスコープ内に再定義前のスコープ変数への参照を持っていれば、その参照を保持しているのでクロージャとしても使える。

var visitCount = function(){
    var count = 1;
    console.log('はじめまして! ○○さん');

    visitCount = function(){
        count++;
        console.log(count + '回目の訪問です');
    }
}

visitCount();  //はじめまして! ○○さん
visitCount();  //2回目の訪問です。
visitCount();  //3回目の訪問です。

連鎖代入

JavaScriptの代入は式なので、演算結果を同じ文のなかでそのままさらに代入することができる(連鎖代入)。
複数の変数にまとめて代入することが必要な場合、以下のように書くことが出来る。

var pamela = otto = 'werewolf';

console.log(pamela); // werewolf
console.log(otto);   // werewolf

一見便利だがスコープの観点からみればあまり好ましくない結果を生んでいる。
たとえば下記のような代入の連鎖は、グローバル空間を汚染している。

// 即時関数で括ってスコープを限定!
(function () {
    var pamela = otto = 'werewolf';
})();

console.log(pamela); // undefined → ok
console.log(otto);   // werewolf   → 見えちゃってる

これは、代入演算子の評価が右結合であることによる。

文『var pamela = otto = 'werewolf';』では、まず式『otto = 'werewolf'』が評価されてしまうため、ottoはグローバル変数として登録されてしまう。 続いて式『var pamela = otto』が評価されるため、var pamelaはグローバルスコープから見えずundefinedとなる。

連鎖代入を用いつつ、pamera・ottoともにスコープをローカルに限定するにはカンマ演算子を使う。

// 即時関数で括ってスコープを限定!
(function () {
    var pamela, otto;
    pamela = otto = 'werewolf';

})();

console.log(pamela); // undefined
console.log(otto);   // undefined
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away