在函数外部存储getElementById是个好主意吗?

时间:2015-10-09 07:44:36

标签: javascript

我认为两个例子最能说明我的问题。

(function(){
  var myBtn = document.getElementById('myBtn');

  function one() {
      console.log(myBtn.innerHtml);
  }
  function two() {
      myBtn.innerHtml = "apple";
  }
  function three() {
      console.log(myBtn.value);
  }
})();

VS

(function(){
  function one() {
      var myBtn = document.getElementById('myBtn');
      console.log(myBtn.innerHtml);
  }
  function two() {
      var myBtn = document.getElementById('myBtn');
      myBtn.innerHtml = "apple";
  }
  function three() {
      var myBtn = document.getElementById('myBtn');
      console.log(myBtn.value);
  }
})();

所以第一个例子使用了一个全局变量(或者当它被一个自调用函数锁定时,它不是一个全局变量?)第二个例子没有。第一个例子是DRY,而第二个例子是将所有内容保存在函数内。

哪一个更好用?两者的优点和缺点是什么?项目规模是否重要?

这也是一个理论上的例子,这些功能显然不会在没有html的情况下发挥作用。感谢。

5 个答案:

答案 0 :(得分:1)

第二个缺点之一是在每个函数中需要再次计算和存储变量。这将对性能产生影响。变量在所有函数中都是相同的,因此您可以在函数1的函数上方将它减去它。示例1中的变量不会成为全局变量(因为使用了iffy)。这也是积极的。需要尽可能保持全球环境的清洁。就个人而言,我认为选项1也更加明显。

答案 1 :(得分:0)

第一个更好用。它提供了更清晰,更快速的代码。

(function(){
  var myBtn = document.getElementById('myBtn');

  function one() {
      console.log(myBtn.innerHtml);
  }
  function two() {
      myBtn.innerHtml = "apple";
  }
  function three() {
      console.log(myBtn.value);
  }
})();

编辑:只需在所有功能中存储和共享结果,就不需要多次运行相同的代码

答案 2 :(得分:0)

document.getElementById函数将返回对指定了ID的第一个对象的引用。这意味着它将在后续调用期间返回对同一对象的引用(在大多数情况下,如果使用得当),它将永远不会引用其他元素,或者无效。

您可以放心地坚持第一个例子的风格。这不是c ++,你的对象不会消失。

答案 3 :(得分:0)

您的问题中有第三种缺失方法:使用对象。

如果myBtn元素在页面生命周期内不会从文档中删除(即直到用户刷新页面 F5 ),作为第一种方法,你应该存储一个引用该元素以避免多次查询文档:

(function() {

  // SomeObject isn't global, but a local variable of IIFE's scope ;)
  var SomeObject = function() {
    this.myBtn = document.getElementById("myBtn");
  };

  SomeObject.prototype = {
    one: function() {
      console.log(this.myBtn.innerHTML);
    },
    two: function() {
      this.myBtn.innerHtml = "apple";
    },

    three: function() {
      console.log(this.myBtn.value);
    }
  };

  // This is required in order to be sure that SomeObject is going to 
  // be able to retrieve "myBtn" element during its construction time,
  // because the document is already loaded
  document.addEventListener("DOMContentLoaded", function() {
    var some = new SomeObject();
    some.one();
  });
})();
<button id="myBtn">My button</button>

答案 4 :(得分:0)

它建议您不使用全局变量的原因是您不会污染全局命名空间。对于闭包,相同的参数将成立。您不希望使用过多的变量污染闭包

所以像

这样的东西
(function(){
  var myBtn = document.getElementById('myBtn');

  function one() {
      console.log(myBtn.innerHtml);
  }
  function two() {
      myBtn.innerHtml = "apple";
  }
  function three() {
      console.log(myBtn.value);
  }
})();

不会污染全局范围,它确实污染了封闭,即想象如果你有类似的东西会有多难维护

(function(){
  var myBtn = document.getElementById('myBtn');

  // lots of code..

  function one() {
      console.log(myBtn.innerHtml);
  }

  // lots of code..

  function two() {
      myBtn.innerHtml = "apple";
  }

  // lots of code..

  function three() {
      console.log(myBtn.value);
  }
})();

因为您必须知道当您在three()时myBtn存在于父作用域中并且在three中创建局部变量时会掩盖该

反对使用外部范围的变量的另一种情况

(function(){
  var myBtn = document.getElementById('myBtn');

  // lots of code..

  function one() {
      console.log(myBtn.innerHtml);
  }

  // lots of code..

  var myBtn1 = document.getElementById('myBtn1');

  function two() {
      myBtn1.innerHtml = "apple";
  }

  // lots of code..

  function three() {
      console.log(myBtn.value);
  }
})();

有一个足够长的外部封闭,你将被迫跟踪myBtn,myBtn1 ....所以虽然这比全局范围(你必须跟踪文件中的变量)更好,现在你(只是?)必须跟踪闭包内的所有变量。

这引出了一个问题,对于大型闭包来说,更好的方法 。这是一个选项

(function () {
    // lots of code..

    function one(myBtn) {
        console.log(myBtn.innerHtml);
    }

    // lots of code..

    function two(myBtn) {
        myBtn.innerHtml = "apple";
    }

    // lots of code..

    function three(myBtn) {
        console.log(myBtn.value);
    }


    var myBtn = document.getElementById('myBtn');

    one(myBtn);
    two(myBtn);
    three(myBtn);
})();

保持一切很好地本地化。当然,如果你有一个大的闭包,这可能表明你在闭包(模块)中做了太多。

当然对于小型封口,你的第一个选择还不错。