日期:2014-05-16  浏览次数:20560 次

【散分】你是如何隐藏你的变量和属性的
这段时间在javascript版块学习了很多,其中感触最深的就是对js继承和对变量的隐藏上。
  我们都知道全局变量的危险性以及可能的与其他库或者js文件冲突问题,所以很多时候我们都在想办法去隐藏我们的全局变量,最简单的方法莫过于加入“命名空间”
JScript code

var Lib = {};
Lib.Do = {};
...



把所有的内容都放到一个Lib里面。这样我们就可以不用为全局变量的污染而担忧了。
  当然,说到js,就不得不提那强大的闭包,在这里我们也可以通过闭包来解决全局变量的污染。比如我们希望构造一个person对象,其对象中有name、age、sex3个属性。那么我们通常的做法是什么呢?
JScript code

function Person(name,age,sex) {
  this.name = name || "jee";
  this.age = age || 24;
  this.sex = sex || true
}


这种模仿类的方法使从类对象语言如(C#、java、C++)等专业的童鞋来说非常的容易接受,我们可以加上属性的getter和setter
Person.prototype.getName = function() {
  return this.name;
};
Person.prototype.setName = function(name) {
  if (name) {
  this.name = name;
  }
}
现在我们理所当然的可以去创建一个对象
JScript code

var p = new Person("jee",24,true);
alert(p.getName());


然而,我们同样可以这样去获取name
JScript code

alert(p.name);


这很糟糕,因为他暴露了我们的属性。通过闭包我们可以去解决这个问题,因为在js中,函数是可以被当作返回值返回的。
JScript code

function person(name,age,sex) {
    var _name = name || "jee";
    var _age = age || 24;
    var _sex = sex || true;
    return {
      getname : function() {
        return _name;
      },
      setname : function(n) {
        _name = n;

      } 
      getage : function() {
        return _age
      }
      ...
    };
}


var p = person("jee",24,true);
这个时候你只能通过getname,setname...等方法来进行属性的存取了。

在这里我遇到过这样一个问题,在使用闭包时,内部的函数使用的是外包函数的实际变量而非copy。我们看这样的代码
HTML code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script type="text/javascript">
    window.onload = function() {
        var li = document.getElementsByTagName("li");
        for (var i = 0; i < li.length; i++) {
            li[i].onclick = function()    {
                alert(i);
            };
        }
    };
</script>
<style>
li    {
    width:100px;
    background-color:red;
    cursor:pointer;
    line-height:20px;
    margin-bottom:5px;
}
</style>
</head>
<body>
    <ul>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</body>
</html>


点击每个li看看发生了什么,对,都是3.因为这是函数构造的时候绑定了i,而非是单纯的得到了i在绑定时的值。这个教训让 我深刻的认识到了这个问题。也在私下找了一些相关资料,现在我们可以把js段代码修改如下
JScript code

    window.onload = function() {
        var li = document.getElementsByTagName("li");
        for (var i = 0; i < li.length; i++) {
            li[i].onclick = function(i)    {
                return function()    {
                    alert(i);
                };
            }(i);//i作为参数传递给这个自执行函数,在绑定onclick的时候,该函数已执行,而这个函数体内部调用的就是该i的值了
        }
    };


在运行看看,好了,可以得到我们想要的结果了,这里勘误