JavaScript - 函数无法从另一个函数范围访问变量

时间:2017-09-09 18:12:33

标签: javascript scope modularity

我正在尝试使用javscript创建一个滑块。我想有两个函数 - 第一个,parseDom(),应该负责从DOM获取元素;第二个configureRange()应负责设置范围属性,例如minmax值。这两个函数都在匿名函数内部调用,该函数被分配给window.onload变量。

function parseDom() {
  var main = document.getElementById('main');
  main.classList.add('red');
  //   red class added - main selector is ok
  var rangeContainer = main.querySelector('.range-container');
  rangeContainer.classList.add('green');
  //   green class added - rangeContainer selector is ok
  var rangeInput = rangeContainer.querySelector('.range-input');
  rangeInput.classList.add('crosshair');
  //   crosshair class added - rangeInput selector is ok

}

function configureRange(){
  rangeInput.classList.add('pointer');
  rangeInput.setAttribute('min', '0');
}

window.onload = function(){
  parseDom();
  configureRange();
}

但是,parseDom()中的变量无法从configureRange()加入,因为这些函数中的变量位于不同的范围内。所以configureRange()中的代码不起作用。我可以在一个函数中而不是两个函数中完成所有操作,但这会使代码变得混乱。如何创建良好的模块化解决方案?

代码在这里: https://codepen.io/t411tocreate/pen/oeKwbW?editors=1111

4 个答案:

答案 0 :(得分:2)

最简单的事情可能是通过configureRange调用它来传递parseDom所需的信息:

function parseDom() {
  var main = document.getElementById('main');
  main.classList.add('red');
  //   red class added - main selector is ok
  var rangeContainer = main.querySelector('.range-container');
  rangeContainer.classList.add('green');
  //   green class added - rangeContainer selector is ok
  var rangeInput = rangeContainer.querySelector('.range-input');
  rangeInput.classList.add('crosshair');
  //   crosshair class added - rangeInput selector is ok
  configureRange(rangeInput);             // <==== Added call
}

function configureRange(rangeInput){      // <==== Note new parameter
  rangeInput.classList.add('pointer');
  rangeInput.setAttribute('min', '0');
}

window.onload = function(){
  parseDom();
  //                                         <==== Removed call
}

...或者通过控制器函数(parseAndConfigure,无论如何)查找输入并将其传递给两个函数。

旁注:在保持函数较小并确保名称表示它的作用(似乎是你的目标)方面,parseDom不解析任何东西,它不仅仅是识别相关的DOM元素(它还为它们添加了类)。也许有三个功能:getDomaddClassesconfigureRange或类似功能。然后:

window.onload = function() {
    var dom = getDom();
    addClasses(dom);
    configureRange(dom);
}

......或类似的东西。

答案 1 :(得分:1)

您可以将元素保留在对象中,然后返回该对象,以便在其他任何地方重用

function parseDom() {
  var els = (function(d) {
    var main           = d.getElementById('main'),
        rangeContainer = main.querySelector('.range-container'),
        rangeInput     = rangeContainer.querySelector('.range-input');

    return {main, rangeContainer, rangeInput};
  })(document);

  els.main.classList.add('red');
  els.rangeContainer.classList.add('green');
  els.rangeInput.classList.add('crosshair');

  return els;
}

function configureRange(els) {
  els.rangeInput.classList.add('pointer');
  els.rangeInput.setAttribute('min', '0');

  return els;
}

window.onload = function() {
  var elems = parseDom();
  configureRange(elems);
}

答案 2 :(得分:1)

最简单的方法是将选择器从parseDom函数中抽象出来,也许可以调用updateDom并解析顶层函数中的选择器,例如:

function updateDom(main, rangeContainer, rangeInput) {
  main.classList.add('red');
  //   red class added - main selector is ok

  rangeContainer.classList.add('green');
  //   green class added - rangeContainer selector is ok

  rangeInput.classList.add('crosshair');
  //   crosshair class added - rangeInput selector is ok

}

function configureRange(rangeInput){
  rangeInput.classList.add('pointer');
  rangeInput.setAttribute('min', '0');
}

window.onload = function(){
  var main = document.getElementById('main'),
    rangeContainer = main.querySelector('.range-container'),
    rangeInput = rangeContainer.querySelector('.range-input');

  updateDom(main, rangeContainer, rangeInput);
  configureRange(rangeInput);
}

答案 3 :(得分:0)

您可以在.onload中声明变量,然后将它们作为参数传递给任意数量的函数:

function parseDom(main, rangeContainer, rangeInput) { // <= arguments
  main.classList.add('red');
  rangeContainer.classList.add('green');
  rangeInput.classList.add('crosshair');
}

function configureRange(rangeInput){ // <= argument
  rangeInput.classList.add('pointer');
  rangeInput.setAttribute('min', '0');
}

window.onload = function(){
  var main = document.getElementById('main'),
    rangeContainer = main.querySelector('.range-container'),
    rangeInput = rangeContainer.querySelector('.range-input'),
    // other elements
  parseDom(main, rangeContainer, rangeInput); // <= pass as arguments
  configureRange(rangeInput); // <= pass as argument
}