日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
淺析JavaScript中的方法鏈

 方法鏈是一種流行的編程方法,可以幫助你寫出更簡潔易讀的代碼。在本文中我們一起學(xué)習(xí) JavaScript 中的方法鏈是什么,以及它是怎樣工作的。另外我們還會探討如何使用方法鏈接來提高代碼的質(zhì)量和可讀性。

JavaScript 中方法鏈

你一定曾經(jīng)用過 jQuery 之類的庫,可能看到過類似的東西。在進行級聯(lián)時主要有兩種方法:一種是一個接一個的執(zhí)行方法,另一種是在同一行上。在純 JavaScript 中這種做法也很普遍。你可以在數(shù)組、字符串和 promise 看到它。

在這些情況下所有的過程都是相同的。首先引用要使用的對象。然后根據(jù)需要使用多種方法。但不是單獨使用這些方法,而要一個接一個地使用。基本上是把它們鏈接在一起。先看一些例子。

方法鏈的例子

在處理字符串時有兩種方法。第一個種不用方法鏈,這要求必須在字符串上分別使用每個方法,這樣必須每次都引用這個字符串。

第二種方式是用方法鏈。這時可以用所有想要的字符串方法。寫出的代碼也可以是單行或多行,這取決于你的習(xí)慣。而且只需要引用一次字符串。盡管結(jié)果相同,但是代碼量卻有很大的差異。

 
 
 
  1. // 在字符串上使用方法鏈的例子
  2. let myStr = ' - Hello-world. '
  3. // 不用方法鏈:
  4. myStr = myStr.toLowerCase()
  5. myStr = myStr.replace(/-/g, ' ')
  6. myStr = myStr.trim()
  7. // 用方法鏈:
  8. myStr = myStr.toLowerCase().replace(/-/g, ' ').trim()
  9. // 多行方法鏈的寫法:
  10. myStr = myStr
  11.   .toLowerCase()
  12.   .replace(/-/g, ' ')
  13.   .trim()
  14. // 查看 "myStr" 的值
  15. console.log(myStr)
  16. // Output:
  17. // 'hello world.'

在數(shù)組上也能用方法鏈:

 
 
 
  1. // 在數(shù)組上使用方法鏈的例子
  2. let myArray = [1, 7, 3, null, 8, null, 0, null, '20', 15]
  3. // 不用方法鏈:
  4. myArray = myArray.filter(el => typeof el === 'number' && isFinite(el))
  5. myArray = myArray.sort((x, y) => x - y)
  6. // 使用方法鏈:
  7. myArray = myArray.filter(el => typeof el === 'number' && isFinite(el)).sort((x, y) => x - y)
  8. // 多行方法鏈的寫法:
  9. myArray = myArray
  10.   .filter(el => typeof el === 'number' && isFinite(el))
  11.   .sort((x, y) => x - y)
  12. // 查看 "myArray" 的值.
  13. console.log(myArray)
  14. // Output:
  15. // [ 0, 1, 3, 7, 8 ]

Promise 是一個很好的例子,因為在使用時差不多全都是方法鏈。首先創(chuàng)建一個 promise,然后添加適當?shù)奶幚砗瘮?shù)。

 
 
 
  1. // 創(chuàng)建 Promise
  2. const myPromise = new Promise((resolve, reject) => {
  3.   // 創(chuàng)建一個假延遲
  4.   setTimeout(function() {
  5.     // 用一條簡單的消息解決諾言 promise
  6.     resolve('Sorry, no data.')
  7.   }, 1000)
  8. })
  9. // 使用方法鏈:
  10. myPromise.then((data) => console.log(data)).catch(err => console.log(error))
  11. // 多行方法鏈的寫法:
  12. myPromise
  13.   .then((data) => console.log(data))
  14.   .catch(err => console.log(error))
  15. // Output:
  16. // 'Sorry, no data.'

方法鏈是怎樣工作的

接下來研究它是怎樣工作的。答案很簡單,是因為 this 。

假設(shè)有一個對象。如果在該對象內(nèi)使用 this,它會引用這個對象。如果創(chuàng)建該對象的實例或副本,則 this 將會引用這個實例或副本。當你使用某些字符串或數(shù)組方法時,實際上是在用一個對象。

 
 
 
  1. const myObj = {
  2.   name: 'Stuart',
  3.   age: 65,
  4.   sayHi() {
  5.     // 這里的 this 是 myObj 的引用
  6.     return `Hi my name is ${this.name}.`
  7.   },
  8.   logMe() {
  9.     console.log(this)
  10.   }
  11. }
  12. myObj.sayHi()
  13. // Output:
  14. // 'Hi my name is Stuart.'
  15. myObj.logMe()
  16. // Output:
  17. // {
  18. //   name: 'Stuart',
  19. //   age: 65,
  20. //   sayHi: ?,
  21. //   logMe: ?
  22. // }

如果是字符串,則使用的是原始數(shù)據(jù)類型。但是你所使用的方法例如 toLowerCase(),存在于 String 對象的原型中。在對象上使用方法鏈還有一個關(guān)鍵要素:this。

為了使鏈起作用,方法必須返回與其一起使用的對象,也就是必須返回 this。就像接力賽跑時的接力棒一樣。

在 JavaScript 中實現(xiàn)方法鏈

為了使方法鏈有效,必須滿足三個條件:首先,需要一些對象。其次,該對象需要一些以后可以調(diào)用的方法。第三,這些方法必須返回對象本身,它們必須返回 this 才能使用方法鏈。

讓我們創(chuàng)建一個簡單的對象 person。person 有 name, age 和 state 屬性。state 用來表示當前處于什么狀態(tài)。要想改變這個狀態(tài),需要用到幾個方法:walk(), sleep(), eat(), drink(), work() 和 exercise()。

由于我們希望所有這些方法都是可鏈的,所以它們都必須返回 this。另外代碼中還有一個用來把當前狀態(tài)記錄到控制臺的工具方法。

 
 
 
  1. // 創(chuàng)建 person 對象
  2. const person = {
  3.   name: 'Jack Doer',
  4.   age: 41,
  5.   state: null,
  6.   logState() {
  7.     console.log(this.state)
  8.   },
  9.   drink() {
  10.     // 修改 person 的 state.
  11.     this.state = 'Drinking.'
  12.     // 把狀態(tài)輸出到控制臺
  13.     this.logState()
  14.     // 返回 this 值。
  15.     return this
  16.   },
  17.   eat() {
  18.     this.state = 'Eating.'
  19.     this.logState()
  20.     return this
  21.   },
  22.   exercise() {
  23.     this.state = 'Exercising.'
  24.     this.logState()
  25.     return this
  26.   },
  27.   sleep() {
  28.     this.state = 'Sleeping.'
  29.     this.logState()
  30.     return this
  31.   },
  32.   walk() {
  33.     this.state = 'Walking.'
  34.     this.logState()
  35.     return this
  36.   },
  37.   work() {
  38.     this.state = 'Working.'
  39.     this.logState()
  40.     return this
  41.   }
  42. }
  43. // 
  44. person
  45.   .drink() // Output: 'Drinking.'
  46.   .exercise() // Output: 'Exercising.'
  47.   .eat() // Output: 'Eating.'
  48.   .work() // Output: 'Working.'
  49.   .walk() // Output: 'Walking.'
  50.   .sleep() // Output: 'Sleeping.'
  51. // 寫在一行上
  52. person.drink().exercise().eat().work().walk().sleep()
  53. // Output:
  54. // 'Drinking.'
  55. // 'Exercising.'
  56. // 'Eating.'
  57. // 'Working.'
  58. // 'Walking.'
  59. // 'Sleeping.'

方法、鏈、this 和箭頭函數(shù)必須使用

也意味著無法使用箭頭函數(shù)創(chuàng)建方法鏈。因為在箭頭函數(shù)中,this 沒有綁定到對象的實例,而是全局對象 window 的引用。如果返回 this,那么返回的不是對象本身而是 window。

另一個問題是從箭頭函數(shù)內(nèi)部訪問和修改對象屬性。由于 this 是全局對象 window,所以不能用它來引用對象及其屬性。

如果你一定要使用箭頭函數(shù),必須想辦法繞過這種方法。不用 this 來引用該對象,必須直接通過其名稱引用該對象,也就是用對象名替換所有出現(xiàn)在箭頭功能內(nèi)的 this。

 
 
 
  1. // 創(chuàng)建 person 對象
  2. const person = {
  3.   name: 'Jack Doer',
  4.   age: 41,
  5.   state: null,
  6.   logState() {
  7.     console.log(this.state)
  8.   },
  9.   drink: () => {
  10.     person.state = 'Drinking.'
  11.     person.logState()
  12.     return person
  13.   },
  14.   eat: () => {
  15.     person.state = 'Eating.'
  16.     person.logState()
  17.     return person
  18.   },
  19.   exercise: () => {
  20.     person.state = 'Exercising.'
  21.     person.logState()
  22.     return person
  23.   },
  24.   sleep: () => {
  25.     person.state = 'Sleeping.'
  26.     person.logState()
  27.     return person
  28.   },
  29.   walk: () => {
  30.     person.state = 'Walking.'
  31.     person.logState()
  32.     return person
  33.   },
  34.   work: () => {
  35.     person.state = 'Working.'
  36.     person.logState()
  37.     return person
  38.   }
  39. }
  40. // 
  41. person
  42.   .drink() // Output: 'Drinking.'
  43.   .exercise() // Output: 'Exercising.'
  44.   .eat() // Output: 'Eating.'
  45.   .work() // Output: 'Working.'
  46.   .walk() // Output: 'Walking.'
  47.   .sleep() // Output: 'Sleeping.'

這樣做的缺點是靈活性不好。如果如果用Object.assign() 和 Object.create()復(fù)制對象,所有箭頭函數(shù)仍然會硬連接到原始對象。

 
 
 
  1. // 創(chuàng)建原始 person 對象
  2. const person = {
  3.   name: 'Jack Doer',
  4.   age: 41,
  5.   state: null,
  6.   logState() {
  7.     // 打印整個對象
  8.     console.log(this)
  9.   },
  10.   drink: () => {
  11.     person.state = 'Drinking.'
  12.     person.logState()
  13.     return person
  14.   },
  15.   eat: () => {
  16.     person.state = 'Eating.'
  17.     person.logState()
  18.     return person
  19.   }
  20. }
  21. // 讓 person eat
  22. person.eat()
  23. // Output:
  24. // {
  25. //   name: 'Jack Doer',
  26. //   age: 41,
  27. //   state: 'Eating.',
  28. //   logState: ?,
  29. //   drink: ?,
  30. //   eat: ?
  31. // }
  32. // 基于person對象創(chuàng)建新對象。
  33. const newPerson = new Object(person)
  34. // 修改 "name" 和 "age" 屬性
  35. newPerson.name = 'Jackie Holmes'
  36. newPerson.age = 33
  37. // 讓 newPerson drink。
  38. // 這會打印 Jack Doer 而不是 Jackie Holmes。
  39. newPerson.drink()
  40. // Output:
  41. // {
  42. //   name: 'Jack Doer',
  43. //   age: 41,
  44. //   state: 'Drinking.',
  45. //   logState: ?,
  46. //   drink: ?,
  47. //   eat: ?
  48. // }

但是,如果用 Object() 構(gòu)造函數(shù),就不會發(fā)生上述問題。如果用 new 關(guān)鍵字的和 Object() 構(gòu)造造函數(shù),將會創(chuàng)建獨立的新對象。當你對這個新對象使用某個方法時,它將僅對這個新對象有效,而對原始對象無效。

 
 
 
  1. // 創(chuàng)建原始 person 對象
  2. const person = {
  3.   name: 'Jack Doer',
  4.   age: 41,
  5.   state: null,
  6.   logState() {
  7.     // 打印整個對象
  8.     console.log(this)
  9.   },
  10.   drink: () => {
  11.     person.state = 'Drinking.'
  12.     person.logState()
  13.     return person
  14.   },
  15.   eat: () => {
  16.     person.state = 'Eating.'
  17.     person.logState()
  18.     return person
  19.   }
  20. }
  21. // 讓 person eat.
  22. person.eat()
  23. // Output:
  24. // {
  25. //   name: 'Jack Doer',
  26. //   age: 41,
  27. //   state: 'Eating.',
  28. //   logState: ?,
  29. //   drink: ?,
  30. //   eat: ?
  31. // }
  32. // 基于 person 對象創(chuàng)建新對象 
  33. const newPerson = new Object(person)
  34. // 修改 "name" 和 "age" 屬性
  35. newPerson.name = 'Jackie Holmes'
  36. newPerson.age = 33
  37. // 讓 newPerson drink.
  38. newPerson.drink()
  39. // Output:
  40. // {
  41. //   name: 'Jackie Holmes',
  42. //   age: 33,
  43. //   state: 'Drinking.',
  44. //   logState: ?,
  45. //   drink: ?,
  46. //   eat: ?
  47. // }

如果你一定要用箭頭功能,并想要復(fù)制對象的話,最好用 Object() 構(gòu)造函數(shù)和 new 關(guān)鍵字創(chuàng)建這些副本。否則只需要用常規(guī)函數(shù)就夠了。

方法鏈和類

如果你喜歡使用 JavaScript 類,也可以在JavaScript中使用方法鏈接。除了語法略又不同外,整個過程和對象是一樣的。但是要注意所有可鏈的方法都必須返回 this。

 
 
 
  1. // 創(chuàng)建 Person 類
  2. class Person {
  3.   constructor(name, age) {
  4.     this.name = name
  5.     this.age = age
  6.     this.state = null
  7.   }
  8.   logState() {
  9.     console.log(this.state)
  10.   }
  11.   drink() {
  12.     this.state = 'Drinking.'
  13.     this.logState()
  14.     return this
  15.   }
  16.   eat() {
  17.     this.state = 'Eating.'
  18.     this.logState()
  19.     return this
  20.   }
  21.   sleep() {
  22.     this.state = 'Sleeping.'
  23.     this.logState()
  24.     return this
  25.   }
  26. }
  27. // 創(chuàng)建 Person 類的實例
  28. const joe = new Person('Joe', 55)
  29. // 使用方法鏈
  30. joe
  31.   .drink() // Output: 'Drinking.'
  32.   .eat() // Output: 'Eating.'
  33.   .sleep() // Output: 'Sleeping.'

總結(jié)

方法鏈是非常有用的,它可以幫你編寫更短、更易讀的代碼。


當前標題:淺析JavaScript中的方法鏈
本文來源:http://www.dlmjj.cn/article/djshhoe.html