这段时间在javascript版块学习了很多,其中感触最深的就是对js继承和对变量的隐藏上。
     我们都知道全局变量的危险性以及可能的与其他库或者js文件冲突问题,所以很多时候我们都在想办法去隐藏我们的全局变量,最简单的方法莫过于加入“命名空间”var Lib = {};
Lib.Do = {};
...
把所有的内容都放到一个Lib里面。这样我们就可以不用为全局变量的污染而担忧了。
    当然,说到js,就不得不提那强大的闭包,在这里我们也可以通过闭包来解决全局变量的污染。比如我们希望构造一个person对象,其对象中有name、age、sex3个属性。那么我们通常的做法是什么呢?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;
   }
}
现在我们理所当然的可以去创建一个对象var p = new Person("jee",24,true);
alert(p.getName());然而,我们同样可以这样去获取namealert(p.name);这很糟糕,因为他暴露了我们的属性。通过闭包我们可以去解决这个问题,因为在js中,函数是可以被当作返回值返回的。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。我们看这样的代码
<!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段代码修改如下 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的值了
}
};在运行看看,好了,可以得到我们想要的结果了,这里勘误一下《javascript语言精粹》里第39页类似例子多了个e,大家把返回函数的参数e去掉就可以正确运行了。
因为这样修改后,onclick绑定的是一个自执行函数返回的一个函数,而这个函数绑定的是作为参数传递进来的i的值。发这个是这段时间对该段内容的理解,由于不是很有把握,所以发在js的版块里算是抛砖引玉,希望各位大牛能够给小弟一些指导。在此谢过。

解决方案 »

  1.   

    我们都是这样隐藏的
    (function() {
        
        var isIE = ....;
        function repaint() {}
        function redraw() {}
        
        function Chart() {}    Chart.prototype = {
            repaint: repaint,
            redraw: redraw
        };    Rs = {
            version: 1.0,
            Chart: Chart
        };
    })();
    内部变量和函数对外部来说都是不可见的。只留了Rs.Chart这样一个接口。外部只需要var chart = new Rs.Chart()就可以chart.redraw()来调用函数。这是最最规范的做法,不知道兄台看懂否?
      

  2.   

    考虑到函数有自己的作用域,也可以这样实现:
      ...
      li[i].onclick = function() {
        this.value = i;
        alert(this.value);
      };
      

  3.   

    hey,牛人我来膜拜你了,给分吧~
      

  4.   

    hey,牛人我来膜拜你了,给分吧~
      

  5.   

    我是直接new Function来搞,window.onload = function() {
            var li = document.getElementsByTagName("li");
            for (var i = 0; i < li.length; i++) {
                li[i].onclick =new Function("alert("+i.toString()+")");
            }
        };
      

  6.   

    【散分】你是如何隐藏你的变量和属性的 [JavaScript]
      

  7.   

    变量的使用域确实很重要,试一试this函数吧。
      

  8.   

    Person.prototype.getName = function() {
      return this.name;
    };
    Person.prototype.setName = function(name) {
      if (name) {
      this.name = name;
      }
    }
    太JAVA了下面这样类似jquery的简洁:
    Person.prototype.attr = function(n,v) {
      if(arguments.length>1)this[n]=v;
      return this[n];
    };
      

  9.   

    泰丰证件.QQ996702552手机18757550100.www.0571banzheng.net
      

  10.   

    (function() {
        
        var isIE = ....;
        function repaint() {}
        function redraw() {}
        
        function Chart() {}    Chart.prototype = {
            repaint: repaint,
            redraw: redraw
        };    Rs = {
            version: 1.0,
            Chart: Chart
        };
    })();
      

  11.   


    兄台知道Rs是什么意思哇。。我写的代码没人理我,这里却有一个随意转载的。
    Rs=Rainsilence
      

  12.   

                        学习“我得分的问题” 精华版——顺便散分,呵呵C++ Builder / 基础类- CSDN ... VB.net与C#哪个比较好?技术、性能及发展前景!(高分呀!) .NET技术 ... 散分200----谈谈c#论坛的结帖率问题.NET技术/ C# - CSDN社区community ... 如何用隐藏域来实现session的功能呢?以使页面长期有效? 【转】【Perl 文档中文化计划】Perl 特殊变量翻译完成。 - 其他开发语言/ 脚 ... [Python]阶乘运算之Python 
      

  13.   


    哎你的文章我读了3遍,根本是完全不一样的东西
    我的代码是针对你的题目给出的。用于解决包与包的变量冲突问题,和属性方法隐藏及类拼接。跟你完全不是一样的想法。
    你的代码里只讲了返回闭包。而且你自己也说没有把握。而且代码难看闭包不是用在这种地方的,你的隐藏可以用这种方式实现。
            function Person(name) {
    var _name = name || "jee";
    this.getName = function() {
    return _name;
    };
    this.setName = function(name) {
    _name = name;
    };
    } var person = new Person("123");
    person.setName(567);
    alert(person.getName());
      

  14.   

    而且
    // lz的代码
    var p = person("jee",24,true);// false
    alert(p instanceof person);// ls的代码
    var person = new Person();
    // true
    alert(person instanceof Person);哎。我啥也不说了
      

  15.   

    嗯 我一开始就说到命名空间一说。和你的解决方案思路一样吧我这段代码的确很丑,呵呵,但是为了下一篇体现出区别,只好这样了。楼上有位老大也提出了太JAVA了。呵呵!
      

  16.   

    很像js框架里面的代码呀
    不过框架一般都是这个格式
    (function(){})()
    不知道是什么意思,可否给我解释下