成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

函數中的 this 不止有 72 變

開發 前端
在課程 連接你、我、他 —— this 中我們學習了 this,最后留了一個問題,如何修改 this 的指向,今天一起學習。

在課程 連接你、我、他 —— this 中我們學習了 this,最后留了一個問題,如何修改 this 的指向,今天一起學習。

修改 this 的指向可通過 apply、call、bind 這三個函數中的任意一個實現。那這三個函數是誰的方法呢?

在 MDN 中我查到了:

這張圖說明了這 3 個函數是 Function prototype 的方法,也就是說「每個函數都有著三個方法」。當定義一個函數,這個函數默認包含這三個方法。

我們感受一下 Vue.js 中關于 apply、call 和 bind 的使用:

apply 的應用:

  1. function once (fn) { 
  2.   var called = false
  3.   return function () { 
  4.     if (!called) { 
  5.       called = true
  6.       fn.apply(this, arguments); 
  7.     } 
  8.   } 

call 的應用:

  1. var hasOwnProperty = Object.prototype.hasOwnProperty; 
  2. function hasOwn (obj, key) { 
  3.   return hasOwnProperty.call(obj, key) 

bind的應用:

  1. function polyfillBind (fn, ctx) { 
  2.   function boundFn (a) { 
  3.     var l = arguments.length; 
  4.     return l 
  5.       ? l > 1 
  6.         ? fn.apply(ctx, arguments) 
  7.         : fn.call(ctx, a) 
  8.       : fn.call(ctx) 
  9.   } 
  10.  
  11.   boundFn._length = fn.length; 
  12.   return boundFn 
  13.  
  14. function nativeBind (fn, ctx) { 
  15.   return fn.bind(ctx) 
  16.  
  17. var bind = Function.prototype.bind 
  18.   ? nativeBind 
  19.   : polyfillBind; 

你可能看不懂上面的用法,下面我們一一拋開謎底。

當一個新事物的出現,總是有目的的,那么 apply、call 和 bind 的出現是為了解決什么問題呢?它們為什么是函數的方法呢?為什么不是其它對象的方法。

通過 apply、call 可以自定義 this 調用某個函數,比如定義一個全局函數(嚴格模式):

  1. 'use strict'; 
  2. function gFun(name, age) { 
  3.     console.log(this); 

這個函數可以通過下面 5 種方式調用,也就是說通過 apply、call、bind 可以調用一個函數 F,其中「函數 F 執行上下文中的 this 可以在調用時指定」:

1.直接調用:

  1. gFun('suyan', 20); // this 為 undefined 

2.通過 this 調用:

  1. this.gFun('suyan', 20); // this 為 window 

3.通過 apply 調用,把所有的參數組合成一個數組作為 apply 的參數:

  1. gFun.apply(this, ['suyan', 20]); // this 為 window 

4.通過 call 調用,參數通過逗號分割,這是與 apply 調用的區別:

  1. gFun.call(this, 'suyan', 20);  // this 為 window 

5.通過 bind 調用,會返回一個原函數的拷貝,并擁有指定的 this和參數:

  1. let bGFun = gFun.bind(this, 'suyan', 20); 
  2. bGFun();  // this 為 window 

我們一起看一些例子:

例1、setTimeOut 的使用:

  1. const time = { 
  2.     second: 1, 
  3.     afterOneSecond() { 
  4.         setTimeout(function () { 
  5.             this.second += 1; 
  6.             console.log(this.second); 
  7.         }, 1000); 
  8.     } 
  9. }; 
  10. time.afterOneSecond(); 

上面這段代碼執行后,第 6 行代碼的打印結果是 NaN,在連接你、我、他 —— this 這節課程中我們有提到過 this 設計的一個弊端是不能繼承。其實可以通過 bind 改造一下這個函數:

  1. const time = { 
  2.     second: 1, 
  3.     afterOneSecond() { 
  4.         setTimeout(this.timeInvoke.bind(this), 1000); 
  5.     }, 
  6.     timeInvoke() { 
  7.         this.second += 1; 
  8.         console.log(this.second); 
  9.     } 
  10. }; 
  11. time.afterOneSecond(); 

函數 timeInvoke 通過 bind 綁定 this,并返回一個新的函數,執行結果為 2。bind 好像具有「暫存」的功能,把當前的 this 暫存起來。

例 2、函數調用

  1. const person = { 
  2.     name: 'suyan', 
  3.     age: 20, 
  4.     showName(pre) { 
  5.         return pre + '-' + this.name; 
  6.     }, 
  7.     update(name, age) { 
  8.         this.name = name; 
  9.         this.age = age; 
  10.     } 
  11. }; 
  12.  
  13. function generateName(fun) { 
  14.     let name = fun(); 
  15.     console.log('showName = ', name); 
  16.  
  17. generateName(person.showName); 

執行上面代碼會報錯,因為 showName 中的 this 為 undefined:

可以通過 bind 「暫存 this」:

  1. const person = { 
  2.     name: 'suyan', 
  3.     age: 20, 
  4.     showName(pre) { 
  5.         return pre + '-' + this.name; 
  6.     }, 
  7.     update(name, age) { 
  8.         this.name = name; 
  9.         this.age = age; 
  10.     } 
  11. }; 
  12.  
  13. function generateName(fun) { 
  14.     let name = fun(); 
  15.     console.log('showName = ', name); 
  16. // 指定 this 為 person 對象 
  17. let bindShowName = person.showName.bind(person, '前端小課'); 
  18. generateName(bindShowName); 

例 3、構造函數,通過 call 來調用某個函數,替換 this。

  1. function Product(name, price) { 
  2.     this.name = name; 
  3.     this.price = price; 
  4.  
  5. function Food(name, price) { 
  6.     // 調用 Product 函數 
  7.     Product.call(this, name, price); 
  8.     this.catagory = 'food'
  9. let food = new Food('包子', 1); 
  10. console.log(food.name); // 包子  

例 4、調用匿名函數

  1. const animals = [ 
  2.     { 
  3.         name: 'King' 
  4.     }, 
  5.     { 
  6.         name: 'Fail' 
  7.     } 
  8. ]; 
  9.  
  10. for (let i = 0; i < animals.length; i++) { 
  11.     (function (i) { 
  12.         // 可以直接使用 this 
  13.         this.print = function () { 
  14.             console.log('#' + i + ' ' + this.name); 
  15.         }; 
  16.         this.print(); 
  17.     }).call(animals[i], i); 

結果為:

回頭再看看課程開始之前 Vue 中關于 apply、call 和 bind 的應用,是不是能看懂了?

 

責任編輯:趙寧寧 來源: 素燕
相關推薦

2010-08-24 10:12:45

2014-01-21 09:29:45

國產操作系統操作系統

2009-08-03 18:24:28

C# 4.0協變和逆變

2020-03-20 19:10:37

支付寶新版移動應用

2015-08-17 11:30:51

2018-04-17 12:28:33

iOS 11.4蘋果ClassKit

2010-04-23 19:54:16

2015-09-10 04:42:10

iPone蘋果發布會

2010-09-09 11:17:44

SQL函數公歷

2020-06-23 15:00:45

AI人工智能遠程辦公

2010-04-23 15:40:26

72ub手機費

2011-01-14 10:27:18

C#.netasp.net

2021-04-16 15:17:19

Windows 10Windows操作系統

2015-02-02 10:03:50

2019-11-25 14:06:44

AI無人駕駛自動駕駛

2024-02-22 12:18:16

Python函數用法

2022-04-18 20:12:03

TypeScript靜態類型JavaScrip

2019-03-11 09:00:00

安全工具病毒軟件惡意軟件
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久精品综合 | 成人不卡在线 | 最新国产在线 | 成人av一区二区亚洲精 | 国产高清免费 | 亚洲成人在线网 | 亚洲一区二区三区在线视频 | 久草网址| 国产一二三区精品视频 | 国产一区二区不卡 | 欧美xxxx做受欧美 | 91视频大全 | 91中文字幕在线 | 天天综合网91 | 久草色视频 | 亚洲一区二区三区 | 91最新在线视频 | 国产一区二区三区在线 | 国产精品久久久久久久久久久免费看 | 亚洲a一区 | 亚洲国产精品久久久久 | 精品一区二区在线观看 | 午夜电影在线播放 | www久久久 | 九九综合 | 国产精品久久久久影院色老大 | 国产精品夜色一区二区三区 | 国产有码| 日韩毛片在线免费观看 | zzzwww在线看片免费 | 国产精品久久久久久吹潮 | 欧美国产视频一区二区 | 亚洲国产精品激情在线观看 | 成人免费av| 久久精品网 | 久久精品—区二区三区 | 在线观看av网站 | 国产 欧美 日韩 一区 | 欧美日韩中文字幕在线 | 日韩一二区在线 | 永久免费av |