<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      apply,call,bind的區(qū)別

      1.apply、call 

      在 javascript 中,call 和 apply 都是為了改變某個(gè)函數(shù)運(yùn)行時(shí)的上下文(context)而存在的,換句話(huà)說(shuō),就是為了改變函數(shù)體內(nèi)部 this 的指向。
      JavaScript 的一大特點(diǎn)是,函數(shù)存在定義時(shí)上下文」「運(yùn)行時(shí)上下文」以及「上下文是可以改變的」這樣的概念。
      先來(lái)一個(gè)例子:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      function fruits() {}
       
      fruits.prototype = {
          color: "red",
          say: function() {
              console.log("My color is " + this.color);
          }
      }
       
      var apple = new fruits;
      apple.say();    //My color is red

       但是如果我們有一個(gè)對(duì)象banana= {color : "yellow"} ,我們不想對(duì)它重新定義 say 方法,那么我們可以通過(guò) call 或 apply 用 apple 的 say 方法:

      1
      2
      3
      4
      5
      banana = {
          color: "yellow"
      }
      apple.say.call(banana);     //My color is yellow
      apple.say.apply(banana);    //My color is yellow

      所以,可以看出 call 和 apply 是為了動(dòng)態(tài)改變 this 而出現(xiàn)的,當(dāng)一個(gè) object 沒(méi)有某個(gè)方法(本栗子中banana沒(méi)有say方法),但是其他的有(本栗子中apple有say方法),我們可以借助call或apply用其它對(duì)象的方法來(lái)操作。 

      2.apply、call 的區(qū)別

       對(duì)于 apply、call 二者而言,作用完全一樣,只是接受參數(shù)的方式不太一樣。例如,有一個(gè)函數(shù)定義如下:

      1
      2
      3
      var func = function(arg1, arg2) {
           
      };

      就可以通過(guò)如下方式來(lái)調(diào)用:

      1
      2
      func.call(this, arg1, arg2);
      func.apply(this, [arg1, arg2])

      其中 this 是你想指定的上下文,他可以是任何一個(gè) JavaScript 對(duì)象(JavaScript 中一切皆對(duì)象),call 需要按順序把一組逗號(hào)分隔的數(shù)據(jù)作為參數(shù)傳遞進(jìn)去,而 apply是傳遞一個(gè)數(shù)組,并把數(shù)組第一項(xiàng)作為函數(shù)的第一個(gè)參數(shù),數(shù)組第二項(xiàng)作為函數(shù)第二個(gè)參數(shù),以此類(lèi)推。

      JavaScript 中,某個(gè)函數(shù)的參數(shù)數(shù)量是不固定的,因此考慮適用條件的話(huà),當(dāng)明確知道參數(shù)數(shù)量時(shí)用 call 。而不確定的時(shí)候用 apply,然后把參數(shù) push 進(jìn)數(shù)組傳遞進(jìn)去。當(dāng)參數(shù)數(shù)量不確定時(shí),函數(shù)內(nèi)部也可以通過(guò) arguments 這個(gè)數(shù)組來(lái)遍歷所有的參數(shù)。
       
      為了鞏固加深記憶,下面列舉一些常用用法:
      1、數(shù)組之間追加
      1
      2
      3
      4
      var array1 = [12 , "foo" , {name "Joe"} , -2458]; 
      var array2 = ["Doe" , 555 , 100]; 
      Array.prototype.push.apply(array1, array2); 
      /* array1 值為  [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */

      2、獲取數(shù)組中的最大值和最小值

      1
      2
      3
      var  numbers = [5, 458 , 120 , -215 ]; 
      var maxInNumbers = Math.max.apply(Math, numbers),   //458
          maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458

      number 本身沒(méi)有 max 方法,但是 Math 有,方法原型是Math.max(value1[,value2, ...]),我們就可以借助 call 或者 apply 使用其方法。

      這里為啥apply會(huì)將第二個(gè)參數(shù)numbers轉(zhuǎn)成單個(gè)的參數(shù)了?它本來(lái)是數(shù)組,這就是apply方法的特性,調(diào)用Math.max方法的時(shí)候,它可以將數(shù)組參數(shù)轉(zhuǎn)換為一個(gè)一個(gè)的參數(shù)。參考MDN上apply方法的原型:

      func.apply(thisArg, [argsArray]):apply() 方法調(diào)用一個(gè)具有給定this值的函數(shù),以及作為一個(gè)數(shù)組(或類(lèi)似數(shù)組對(duì)象)提供的參數(shù)。

      參數(shù)介紹如下:

      參數(shù)

      thisArg
      必選的。在 func 函數(shù)運(yùn)行時(shí)使用的 this 值。請(qǐng)注意,this可能不是該方法看到的實(shí)際值:如果這個(gè)函數(shù)處于非嚴(yán)格模式下,則指定為 null 或 undefined 時(shí)會(huì)自動(dòng)替換為指向全局對(duì)象,原始值會(huì)被包裝。
      argsArray
      可選的。一個(gè)數(shù)組或者類(lèi)數(shù)組對(duì)象,其中的數(shù)組元素將作為單獨(dú)的參數(shù)傳給 func 函數(shù)。如果該參數(shù)的值為 null 或  undefined,則表示不需要傳入任何參數(shù)。從ECMAScript 5 開(kāi)始可以使用類(lèi)數(shù)組對(duì)象。 瀏覽器兼容性 請(qǐng)參閱本文底部?jī)?nèi)容。

      3、驗(yàn)證是否是數(shù)組(前提是toString()方法沒(méi)有被重寫(xiě)過(guò))

      1
      2
      3
      functionisArray(obj){ 
          return Object.prototype.toString.call(obj) === '[object Array]' ;
      }

      4、類(lèi)(偽)數(shù)組使用數(shù)組方法

      1
      var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
      Javascript中存在一種名為偽數(shù)組的對(duì)象結(jié)構(gòu)。比較特別的是 arguments對(duì)象,還有像調(diào)用 getElementsByTagName , document.childNodes 之類(lèi)的,它們返回NodeList對(duì)象都屬于偽數(shù)組。不能應(yīng)用 Array下的 push , pop 等方法。
      但是我們能通過(guò) Array.prototype.slice.call (方法原型為arr.slice([begin[, end]]))轉(zhuǎn)換為真正的數(shù)組的帶有 length 屬性的對(duì)象,這樣 domNodes 就可以應(yīng)用 Array下的所有方法了。 數(shù)組的slice方法如果不指起始處索引start,默認(rèn)是0,不指定終止處索引end,則默認(rèn)是數(shù)組末尾array.length-1

      3.深入理解運(yùn)用apply、call

      下面就用一個(gè)例子,來(lái)更深入的去理解下 apply 和 call 。

      定義一個(gè) log 方法,讓它可以代理 console.log 方法,常見(jiàn)的解決方法是:

      1
      2
      3
      4
      5
      function log(msg) {
        console.log(msg);
      }
      log(1);    //1
      log(1,2);    //1

      上面方法可以解決最基本的需求,但是當(dāng)傳入?yún)?shù)的個(gè)數(shù)是不確定的時(shí)候,上面的方法就失效了,這個(gè)時(shí)候就可以考慮使用 apply 或者 call,注意這里傳入多少個(gè)參數(shù)是不確定的,所以使用apply是最好的,方法如下:

      1
      2
      3
      4
      5
      function log(){
        console.log.apply(console, arguments);
      };
      log(1);    //1
      log(1,2);    //1 2

      接下來(lái)的要求是給每一個(gè) log 消息添加一個(gè)"(app)"的前輟,比如:

      1
      log("hello world");    //(app)hello world

      該怎么做比較優(yōu)雅呢?這個(gè)時(shí)候需要想到arguments參數(shù)是個(gè)偽數(shù)組,通過(guò) Array.prototype.slice.call 轉(zhuǎn)化為標(biāo)準(zhǔn)數(shù)組,再使用數(shù)組方法unshift,像這樣:

      1
      2
      3
      4
      5
      6
      function log(){
        var args = Array.prototype.slice.call(arguments);
        args.unshift('(app)');
       
        console.log.apply(console, args);
      };

      4.bind

      說(shuō)完了 apply 和 call ,再來(lái)說(shuō)說(shuō)bind。bind() 方法與 apply 和 call 很相似,也是可以改變函數(shù)體內(nèi) this 的指向。

      MDN的解釋是:bind()方法會(huì)創(chuàng)建一個(gè)新函數(shù),稱(chēng)為綁定函數(shù),當(dāng)調(diào)用這個(gè)綁 定函數(shù)時(shí),綁定函數(shù)會(huì)以創(chuàng)建它時(shí)傳入 bind()方法的第一個(gè)參數(shù)作為 this,傳入 bind() 方法的第二個(gè)以及以后的參數(shù)加上綁定函數(shù)運(yùn)行時(shí) 本身的參數(shù)按照順序作為原函數(shù)的參數(shù)來(lái)調(diào)用原函數(shù)。

      直接來(lái)看看具體如何使用,在常見(jiàn)的單體模式中,通常我們會(huì)使用 _this , that , self 等保存 this ,這樣我們可以在改變了上下文之后繼續(xù)引用到它。 像這樣:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      var foo = {
          bar : 1,
          eventBind: function(){
              var _this = this;
              $('.someClass').on('click',function(event) {
                  /* Act on the event */
                  console.log(_this.bar);     //1
              });
          }
      }

      由于 Javascript 特有的機(jī)制,上下文環(huán)境在 eventBind:function(){ } 過(guò)渡到 $('.someClass').on('click',function(event) { }) 發(fā)生了改變,上述使用變量保存 this 這些方式都是有用的,也沒(méi)有什么問(wèn)題。當(dāng)然使用 bind() 可以更加優(yōu)雅的解決這個(gè)問(wèn)題:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      var foo = {
          bar : 1,
          eventBind: function(){
              $('.someClass').on('click',function(event) {
                  /* Act on the event */
                  console.log(this.bar);      //1
              }.bind(this));
          }
      }

      在上述代碼里,bind() 創(chuàng)建了一個(gè)函數(shù),當(dāng)這個(gè)click事件綁定在被調(diào)用的時(shí)候,它的 this 關(guān)鍵詞會(huì)被設(shè)置成被傳入的值(這里指調(diào)用bind()時(shí)傳入的參數(shù))。因此,這里我們傳入想要的上下文 this(其實(shí)就是 foo ),到 bind() 函數(shù)中。然后,當(dāng)回調(diào)函數(shù)被執(zhí)行的時(shí)候, this 便指向 foo 對(duì)象。再來(lái)一個(gè)簡(jiǎn)單的栗子:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      var bar = function(){
      console.log(this.x);
      }
      var foo = {
      x:3
      }
      bar(); // undefined
      var func = bar.bind(foo);
      func(); // 3

      這里我們創(chuàng)建了一個(gè)新的函數(shù) func,當(dāng)使用 bind() 創(chuàng)建一個(gè)綁定函數(shù)之后,它被執(zhí)行的時(shí)候,它的 this 會(huì)被設(shè)置成 foo , 而不是像我們調(diào)用 bar() 時(shí)的全局作用域。

      有個(gè)有趣的問(wèn)題,如果連續(xù) bind() 兩次,亦或者是連續(xù) bind() 三次那么輸出的值是什么呢?像這樣:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      var bar = function(){
          console.log(this.x);
      }
      var foo = {
          x:3
      }
      var sed = {
          x:4
      }
      var func = bar.bind(foo).bind(sed);
      func(); //?
       
      var fiv = {
          x:5
      }
      var func = bar.bind(foo).bind(sed).bind(fiv);
      func(); //?

      答案是,兩次都仍將輸出 3 ,而非期待中的 4 和 5 。原因是,在Javascript中,多次 bind() 是無(wú)效的。更深層次的原因, bind() 的實(shí)現(xiàn),相當(dāng)于使用函數(shù)在內(nèi)部包了一個(gè) call / apply ,第二次 bind() 相當(dāng)于再包住第一次 bind() ,故第二次以后的 bind 是無(wú)法生效的。  

      6.apply、call、bind比較

      那么 apply、call、bind 三者相比較,之間又有什么異同呢?何時(shí)使用 apply、call,何時(shí)使用 bind 呢。簡(jiǎn)單的一個(gè)栗子:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      var obj = {
          x: 81,
      };
       
      var foo = {
          getX: function() {
              return this.x;
          }
      }
       
      console.log(foo.getX.bind(obj)());  //81
      console.log(foo.getX.call(obj));    //81
      console.log(foo.getX.apply(obj));   //81

      三個(gè)輸出的都是81,但是注意看使用 bind() 方法的,他后面多了對(duì)括號(hào)。

      也就是說(shuō),區(qū)別是,當(dāng)你希望改變上下文環(huán)境之后并非立即執(zhí)行,而是回調(diào)執(zhí)行的時(shí)候,使用 bind() 方法。而 apply/call 則會(huì)立即執(zhí)行函數(shù)。 

      再總結(jié)一下:

      • apply 、 call 、bind 三者都是用來(lái)改變函數(shù)的this對(duì)象的指向的;
      • apply 、 call 、bind 三者第一個(gè)參數(shù)都是this要指向的對(duì)象,也就是想指定的上下文;
      • apply 、 call 、bind 三者都可以利用后續(xù)參數(shù)傳參;
      • bind 是返回對(duì)應(yīng)函數(shù),便于稍后調(diào)用;apply 、call 則是立即調(diào)用 。
      posted @ 2015-10-09 15:34  nd  閱讀(1621)  評(píng)論(1)    收藏  舉報(bào)
      主站蜘蛛池模板: 国产精品日韩中文字幕| 国产在线精品中文字幕| 无遮挡高潮国产免费观看| 免费大片黄国产在线观看| 无码av中文一区二区三区桃花岛| 日韩乱码卡一卡2卡三卡四| 伊人久久大香线蕉AV网禁呦| 国产亚洲精品第一综合| 国产美女午夜福利视频| 亚洲最大成人美女色av| 综1合AV在线播放| 双城市| 国产一级精品在线免费看| 丰满少妇被猛烈进出69影院| 国产无遮挡又黄又爽又色| 极品无码国模国产在线观看| 精品亚洲一区二区三区四区| 92国产福利午夜757小视频| 亚洲精品免费一二三区| 精品久久久久久无码人妻蜜桃 | 人妻一区二区三区三区| 国产成人精品久久一区二区| 国产精品大片中文字幕| 亚洲欧洲日产国码无码久久99| 视频一区二区三区刚刚碰| 亚洲精品免费一二三区| 又黄又爽又色视频免费| 亚洲性一交一乱一伦视频| 熟女一区二区中文字幕| 蜜桃av色偷偷av老熟女| 国产精品福利自产拍久久| 国产成人亚洲欧美二区综合| 狠狠色噜噜狠狠狠狠色综合网| 国产精品一区二区色综合| 亚洲欧美国产日韩天堂区| 亚洲国产aⅴ成人精品无吗| 国产精品白丝一区二区三区| 男人狂桶女人高潮嗷嗷| 人妻日韩人妻中文字幕| 日韩人妻少妇一区二区三区 | 茄子视频国产在线观看|