| 网站首页 | 文章中心 | 设计欣赏 | 下载中心 | 设计咨讯 | 平面设计 | 二维|三维 | 网页制作 | NIIT论坛 | 酷站! | 
    您现在的位置: 卓越设计网 >> 网页制作 >> Javascript >> 网页制作正文
javascript中的作用域           
javascript中的作用域
作者:网站建设 文章来源:网页制作 点击数: 更新时间:2007-8-3 8:18:29

任何相关对象的奇幻东西,我们只是呼叫一个普通的、常见的函数,在这种情形下this表示的又是什么呢?

<script type="text/javascript">
  function test_this() {
   return this;
  }
  var i_wonder_what_this_is = test_this();
</script>

在这样的场合,我们并不通过new来提供上下文,也不会以某种对象形式在背后偷偷提供上下文。在此, this默认下尽可能引用最全局的东西:对于网页来说,这就是 window对象。

  • 事件处理函数

    比普通函数的呼叫更复杂的状况,先假设我们使用函数去处理的是一个onclick事件。当事件触发我们的函数运行,此处的this表示的是什么呢?不凑巧,这个问题不会有简单的答案。

    如果我们写的是行内(inline)事件处理函数,this引用的是全局window对象:

    <script type="text/javascript">
      function click_handler() {
       alert(this); // 弹出 window 对象
      }
    </script>
     ...
    <button id='thebutton' onclick='click_handler()'>Click me!</button>

    但是,如果我们通过JavaScript来添加事件处理函数,this引用的是生成该事件的DOM元素。(注意:此处的事件处理非常简洁和易于阅读,但其他的就别有洞天了。请使用 真正的addEvent函数 取而代之):

    <script type="text/javascript">
      function click_handler() {
       alert(this); // 弹出按钮的DOM节点
      }

      function addhandler() {
       document.getElementById('thebutton').onclick = click_handler;
      }

      window.onload = addhandler;
    </script>
     ...
    <button id='thebutton'>Click me!</button>

  • 复杂情况

    让我们来短暂地运行一下这个最后的例子。我们需要询问deep_thought一个问题,如果不是直接运行click_handler而是通过点击按钮的话,那会发生什么事情?解决此问题的代码貌似十分直接,我们可能会这样做:

    <script type="text/javascript">
     function BigComputer(answer) {
      this.the_answer = answer;
      this.ask_question = function () {
       alert(this.the_answer);
      }
     }

     function addhandler() {
      var deep_thought = new BigComputer(42),
       the_button = document.getElementById('thebutton');

      the_button.onclick = deep_thought.ask_question;
     }

     window.onload = addhandler;
    </script>

    很完美吧?想象一下,我们点击按钮,deep_thought.ask_question被执行,我们也得到了“42”。但是为什么浏览器却给我们一个undefined? 我们错在何处?

    其实问题显而易见:我们给ask_question传递一个引用,它作为一个事件处理函数来执行,与作为对象方法来运行的上下文并不一样。简而言之,ask_question中的 this关键字指向了产生事件的DOM元素,而不是在BigComputer的对象中。DOM元素并不存在一个the_answer属性,所以我们得到的是 undefined而不是”42″. setTimeout也有类似的行为,它在延迟函数执行的同时跑到了一个全局的上下文中去了。

    这个问题会在程序的所有角落时不时突然冒出,如果不细致地追踪程序的每一个角落的话,还是一个非常难以排错的问题,尤其在你的对象有跟DOM元素或者window对象同名属性的时候。

    使用.apply()和.call()掌控上下文

    在点击按钮的时候,我们真正需要的是能够咨询deep_thought一个问题,更进一步说,我们真正需要的是,在应答事件和setTimeout的呼叫时,能够在自身的本原上下文中呼叫对象的方法。有两个鲜为人知的JavaScript方法,apply和call,在我们执行函数呼叫时,可以曲线救国帮我们达到目的,允许我们手工覆盖this的默认值。我们先来看call:

    <script type="text/javascript">
     var first_object = {
      num: 42
     };
     var second_object = {
      num: 24
     };

     function multiply(mult) {
      return this.num * mult;
     }

     multiply.call(first_object, 5); // 返回 42 * 5
     multiply.call(second_object, 5); // 返回 24 * 5
    </script>

    在这个例子中,我们首先定义了两个对象,first_object和second_object,它们分别有自己的num属性。然后定义了一个multiply函数,它只接受一个参数,并返回该参数与this所指对象的num属性的乘积。如果我们呼叫函数自身,返回的答案极大可能是undefined,因为全局window对象并没有一个num属性除非有明确的指定。我们需要一些途径来告诉multiply里面的this关键字应该引用什么。而multiply的call方法正是我们所需要的。

    call的第一个参数定义了在业已执行的函数内this的所指对象。其余的参数则传入业已执行的函数内,如同函数的自身呼叫一般。所以,当执行multiply.call(first_object, 5)时,multiply被呼叫,5传入作为第一个参数,而this关键字被设置为first_object的引用。同样,当执行multiply.call(second_object, 5)时,5传入作为第一个参数,而this关键字被设置为second_object的引用。

    apply以call一样的方式工作,但可以让你把参数包裹进一个数组再传递给呼叫函数,在程序性生成函数呼叫时尤为有用。使用apply重现上一段代码,其实区别并不大:

    <script type="text/javascript">
     ...

     multiply.apply(first_object, [5]); // 返回 42 * 5
     multiply.apply(second_object, [5]); // 返回 24 * 5
    </script>

    apply和call本身都非常有用,并值得贮藏于你的工具箱内,但对于事件处理函数所改变的上下文问题,也只是送佛到西天的中途而已,剩下的还是得我们来解决。在搭建处理函数时,我们自然而然地认为,只需简单地通过使用call来改变this的含义即可:

    上一页  [1] [2] [3] 下一页


    网页制作录入:as8130239    责任编辑:as8130239 
  • 上一篇网页制作:

  • 下一篇网页制作: 没有了
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    网站
    导航
        最新图片
       推荐信息
       最 新 热 门
        最 新 推 荐
        相 关 文 章
    没有相关网页制作