2017-10-03 9 views
3

コードを乾燥させるために、よく使うif/else文を取り、関数に変換することに決めました。この関数をforEachループに適用しようとしましたが、関数のパラメータが定義されていないというエラーが発生しています。for eachループ内のパラメータを持つ関数の使用

は、ここでは、コードです:

var addClass = (className) => { 
    (this.classList.contains(className) === true) 
     ? this.classList.remove('active') & this.classList.add(className) 
     : this.classList.add(className); 
} 

exploreStory_buttons.forEach(el => el.addEventListener('mouseover'), addClass(active)); 

私が間違ってやっているに任意の洞察力をいただければ幸いです。いつものように、私は解決策が単純かもしれないかのように感じます:私はそれを見ていないだけです。

+5

'addClass(アクティブ)' 'active'したがって、関数に渡すパラメータが定義されていない、未定義の変数です。 ''アクティブ ''でなければなりません。 –

+0

@ JeremyThille私は実際にはパラメータ括弧内にアクティブな引用符を入れようとしていましたが、うまくいきませんでした。 – cpsavante

+0

BTW '&'はビット単位の演算子ですから、おそらく短絡操作のために '&&'を意味しています。それ以外に同じクラスを追加する理由は何ですか? – Redu

答えて

6

適切なコンテキストで関数を呼び出したいとします。そのためにはFunction#callがあります。また、通常の関数を使用する必要があります。「太い矢印」関数はthisの扱いが異なります。

var addClass = function (className) { 
    if (this.classList.contains(className)) { 
     this.classList.remove('active'); 
     this.classList.add(className); 
    } else { 
     this.classList.add(className); 
    } 
} 

exploreStory_buttons.forEach(el => { 
    el.addEventListener('mouseover'); // where is the event listener?? 
    addClass.call(this, active); // N.B. active is undefined here. Do you mean "active"? 
}); 

「スマート」コードを書くために言語機能を悪用したくない場合もあります。複数の文に対してif/elseと複数行を使用すると、コード難読化プログラムではありません。あなたは「ホバー」動作を追加したいと仮定すると、


、コードは次のようになり何かだろう:

function addClass(className) { 
    return function() { 
     this.classList.add(className); 
    } 
} 
function removeClass(className) { 
    return function() { 
     this.classList.remove(className); 
    } 
} 

var activate = addClass('active'); 
var deactivate = removeClass('active'); 

exploreStory_buttons.forEach(el => { 
    el.addEventListener('mouseenter', activate); 
    el.addEventListener('mouseleave', deactivate); 
}); 

注意をどのようにイベントハンドラとして機能することができaddClassremoveClassリターン機能。変数をactivatedeactivateという変数に格納するということは、ループ内に複数の等価な関数のコピーを作成していないことを意味しますが、実際にはすべての要素に同じ関数を割り当てます。


activate/deactivate変数や関数を返す関数hover()機能を実装することで回避することができます(jQueryのsimilar featureを持っている):

function hover(elements, onenter, onleave) { 
    elements.forEach(el => { 
     el.addEventListener('mouseenter', onenter); 
     el.addEventListener('mouseleave', onleave); 
    }); 
} 

hover(exploreStory_buttons, function() { 
    this.addClass('active'); 
}, function() { 
    this.removeClass('active'); 
}); 

ここでは、イベントハンドラ関数は一度だけと直接作成されていますどこに必要なのですか?それらをヘルパー変数に格納するよりもずっと優れています。

+0

提案と推奨の両方をありがとうございます。 'コードobfuscator'はかなりクイック笑です。私はあなたのソリューションを実装しようとしたが、addEventListenerがイベントターゲットで実行に失敗したというエラーメッセージが表示されています.2つの引数は必要ですが、1つしか存在しません。そして、私は、今のところ、それがどういう意味をしているのかはかなりわかっています – cpsavante

+0

これは私のコメント '/ /どこでイベントリスナーですか?私の答えの残りの部分も読んでください。 – Tomalak

+0

これは私が自分のコードに理解していることを実装するために最善を尽くしてはいますが、私の周りを包み込むことはかなり恥ずかしいものです。これらは間違いなく私が前に出会ったことのない概念です。私は次のように尋ねたいと思います:あなたは、提供された例の関数からifステートメントを削除しました。これは単純にあなたの実装では必要ないためですか?それとも、ポイントを共有する必要がないため、単に追加していないだけですか? – cpsavante

1

あなたのコードにはいくつかの問題があります。

  1. 私はmouseoverにあなたがアクティブに要素のクラスを変更したいと仮定します。この場合、addClass関数は別の関数を返さなければなりませんが、太い矢印ではなく正規のものを返さなければなりません。

    this.classList.remove('active') & this.classList.add(className)

または論理AND:

  • はあなたが本当にビット単位を望んでいたし、このライン上でしたか?

    exploreStory_buttons = document.getElementsByClassName('explore-story'); 
     
    var addClass = (className) => function() { 
     
        this.classList.contains(className) 
     
         ? (this.classList.remove('active') && this.classList.add(className)) 
     
         : this.classList.add(className); 
     
    } 
     
    
     
    
     
    Array.prototype.forEach.call(exploreStory_buttons, (el) => el.addEventListener('mouseover', addClass.call(el, 'active')));
    .active { 
     
        color: red 
     
    }
    <button class="explore-story active">Story 1</button> 
     
    <button class="explore-story">Story 2</button>

  • +0

    ああ、私は間違いなく機能的なものを使うことを意図していた。あなたが私にそれを指摘していないと、私はそのエラーを捕まえたことはないだろう。大変ありがとう! – cpsavante

    関連する問題