国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
JavaScript的this,call(),apply(),bind()

JavaScript的this,call(),apply(),bind()

為了建立一個scope chain, 每個JavaScript的代碼執(zhí)行上下文都提供了this關(guān)鍵字。In its most common usage, thisserves as an identity function, providing our neighborhoods a way ofreferring to themselves. We can’t always rely on that behavior,however: Depending on how we get into a particular neighborhood, this might mean something else entirely. In fact, how we get into the neighborhood is itself exactly what this generally refers to. 需要注意特殊的四種情況:

  • Calling an Object’s Method

    在典型的面向?qū)ο缶幊虝r(shí),我們需要一種方式去指向和引用我們調(diào)用的對象. this serves the purpose admirably, providing our objects the ability to examine themselves, and point at their own properties.

     <script type="text/javascript">
      var deep_thought = {
       the_answer: 42,
       ask_question: function () {
        return this.the_answer;
       }
      };
     
      var the_meaning = deep_thought.ask_question();
     </script>

    This example builds an object named deep_thought, sets its the_answer property to 42, and creates an ask_question method. When deep_thought.ask_question() is executed, JavaScript establishes an execution context for the function call, setting this to the object referenced by whatever came before the last ”.”, in this case: deep_thought. The method can then look in the mirror via this to examine its own properties, returning the value stored in this.the_answer: 42.

  • Constructor

    Likewise, when defining a function to be used as a constructor with the new keyword, this can be used to refer to the object being created. Let’s rewrite the example above to reflect that scenario:

     <script type="text/javascript">
      function BigComputer(answer) {
       this.the_answer = answer;
       this.ask_question = function () {
        return this.the_answer;
       }
      }
     
      var deep_thought = new BigComputer(42);
      var the_meaning = deep_thought.ask_question();
     </script>

    Instead of explicitly creating the deep_thought object, we’ll write a function to create BigComputer objects, and instantiate deep_thought as an instance variable via the new keyword. When new BigComputer() is executed, a completely new object is created transparently in the background. BigComputer is called, and its this keyword is set to reference that new object. The function can set properties and methods on this, which is transparently returned at the end of BigComputer’s execution.

    Notice, though, that deep_thought.the_question() still works just as it did before. What’s going on there? Why does this mean something different inside the_question than it does inside BigComputer? Put simply, we entered BigComputer via new, so this meant “the new object.” On the other hand, we entered the_question via deep_thought, so while we’re executing that method, this means “whatever deep_thought refers to”. this is not read from the scope chain as other variables are, but instead is reset on a context by context basis.

  • Function Call

    What if we just call a normal, everyday function without any of this fancy object stuff? What does this mean in that scenario?

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

    In this case, we weren’t provided a context by new, nor were we given a context in the form of an object to piggyback off of. Here, this defaults to reference the most global thing it can: for web pages, this is the window object.

  • Event Handler

    For a more complicated twist on the normal function call, let’s say that we’re using a function to handle an onclick event. What does this mean when the event triggers our function’s execution? Unfortunately, there’s not a simple answer to this question.

    If we write the event handler inline, this refers to the global window object:

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

    However, when we add an event handler via JavaScript, this refers to the DOM element that generated the event. (Note: The event handling shown here is short and readable, but otherwise poor. Please use a real addEvent function instead.):

     <script type="text/javascript">
      function click_handler() {
       alert(this); // alerts the button DOM node
      }
     
      function addhandler() {
       document.getElementById('thebutton').onclick = click_handler;
      }
     
      window.onload = addhandler;
     </script>
     ...
     <button id='thebutton'>Click me!</button>

Complications

Let’s run with that last example for a moment longer. What if instead of running click_handler, we wanted to ask deep_thought a question every time we clicked the button? The code for that seems pretty straightforward; we might try this:

<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>

對上面的代碼,我們期望點(diǎn)擊按鈕, deep_thought.ask_question被執(zhí)行,我們得到返回結(jié)果“42.” 但為什么得到的結(jié)果反而是undefined?哪里錯了?

The problem is simply this: We’ve passed off a reference to the ask_questionmethod, which, when executed as an event handler, runs in a differentcontext than when it’s executed as an object method. 簡而言之,ask_question 中的this關(guān)鍵字是指向產(chǎn)生事件的DOM元素節(jié)點(diǎn),而不是BigComputer對象. DOM元素節(jié)點(diǎn)并沒有the_answer屬性,所以返回結(jié)果是undefined而不是“42.” setTimeout exhibits similar behavior, delaying the execution of a function while at the same time moving it out into a global context.

This issue crops up all over the place in our programs, and it’s aterribly difficult problem to debug without keeping careful track ofwhat’s going on in all the corners of your program, especially if yourobject has properties that do exist on DOM elements or the window object.

Manipulating Context With .apply() and .call()

We really do want to be able to ask deep_thought a question when we click the button, and more generally, we do want to be able to call object methods in their native context when responding to things like events and setTimeout calls. Two little-known JavaScript methods, apply and call, indirectly enable this functionality by allowing us to manually override the default value of this when we execute a function call. Let’s look at call first:

<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); // returns 42 * 5
 multiply.call(second_object, 5); // returns 24 * 5
</script>

In this example, we first define two objects, first_object and second_object, each with a num property. Then we define a multiply function that accepts a single argument, and returns the product of that argument, and the num property of its this object. If we called that function by itself, the answer returned would almost certainly be undefined, since the global window object doesn’t have a num property unless we explicitly set one. We need some way of telling multiply what its this keyword ought refer to; the call method of the multiply function is exactly what we’re looking for.

 call方法的第一個參數(shù)定義了this關(guān)鍵字在被調(diào)用方法的執(zhí)行上下文中指向和對象,call方法的剩余參數(shù)則是被調(diào)用方法的參數(shù)。因此當(dāng)multiply.call(first_object, 5)被執(zhí)行, multiply函數(shù)被調(diào)用, 5 為傳入方法的第一個參數(shù), this 執(zhí)行 first_object對象。 Likewise, when multiply.call(second_object, 5) is executed, the multiply function is called, 5 is passed in as the first argument, and the this keyword is set to refer to object second_object.

apply方法和 call方法基本一致,但是允許你以數(shù)組的形式向被調(diào)用的函數(shù)傳遞參數(shù),which can be quite useful when programatically generating functioncalls. Replicating the functionality we just talked about using apply is trivial:

<script type="text/javascript">
 ...
 
 multiply.apply(first_object, [5]); // returns 42 * 5
 multiply.apply(second_object, [5]); // returns 24 * 5
</script>

apply and call are very useful on theirown, and well worth keeping around in your toolkit, but they only getus halfway to solving the problem of context shifts for event handlers.It’s easy to think that we could solve the problem by simply using call to shift the meaning of this when we set up the handler:

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

上面的代碼仍然存在問題: call是立即執(zhí)行函數(shù)的,因此我們提供的 onclick handler是函數(shù)的執(zhí)行結(jié)果而不是函數(shù)本身.我們需要JavaScript的另一個特性來解決這個問題:bind方法。

The Beauty of .bind()

I’m not a huge fan of the Prototype JavaScript framework, but I am very much impressed with the quality of its code as a whole. In particular, one simple addition it makes to the Function object has had a hugely positive impact on my ability to manage the context in which function calls execute: bind performs the same general task as call, altering the context in which a function executes. The difference is that bind returns a function reference that can be used later, rather than the result of an immediate execution that we get with call.

If we simplify the bind function a bit to get at thekey concepts, we can insert it into the multiplication example wediscussed earlier to really dig into how it works; it’s quite anelegant solution:

<script type="text/javascript">
 var first_object = {
  num: 42
 };
 var second_object = {
  num: 24
 };
 
 function multiply(mult) {
  return this.num * mult;
 }
 
 Function.prototype.bind = function(obj) {
  var method = this,
   temp = function() {
    return method.apply(obj, arguments);
   };
 
  return temp;
 }
 
 var first_multiply = multiply.bind(first_object);
 first_multiply(5); // returns 42 * 5
 
 var second_multiply = multiply.bind(second_object);
 second_multiply(5); // returns 24 * 5
</script>

First, we define first_object, second_object, and the multiply function, just as before. With those taken care of, we move on to creating a bind method on the Function object’s prototype, which has the effect of making bind available for all functions in our program. When multiply.bind(first_object) is called, JavaScript creates an execution context for the bind method, setting this to the multiply function, and setting the first argument, obj, to reference first_object. So far, so good.

The real genius of this solution is the creation of method, set equal to this (the multiply function itself). When the anonymous function is created on the next line, method is accessible via its scope chain, as is obj (this couldn’t be used here, because when the newly created function is executed, this will be overwritten by a new, local context). This alias to this makes it possible to use apply to execute the multiply function, passing in obj to ensure that the context is set correctly. In computer-science-speak, temp is a closure that, when returned at the end of the bind call, can be used in any context whatsoever to execute multiply in the context of first_object.

This is exactly what we need for the event handler and setTimeout scenarios discussed above. The following code solves that problem completely, binding the deep_thought.ask_question method to the deep_thought context, so that it executes correctly whenever the event is triggered:

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

Beautiful.

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
js再論call和apply
前端整理——javaScript部分
前端面試題之JavaScript
javascript的動態(tài)this與動態(tài)綁定
Javascript通過bind()掌控this
bind,call,apply模擬實(shí)現(xiàn)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服