在普通函数中也返回当前实例,我们就可以使用 . 在单行代码中,
一次性连续调用多个方法,就好像它们被链接在一起一样,这就是链式调用,又称链模式
jQuery、Promise 等也使用了链模式
https://www.h5w3.com/29942.html

jquery的链式调用:选择元素,然后从上到下依次进行一系列操作

  1. $('div')
  2. .show()
  3. .addClass('active')
  4. .height('100px')
  5. .css('color', 'red')
  6. .on('click', function(e) {
  7. // ...
  8. })
  9. // 不使用链模式
  10. var divEls = $('div')
  11. divEls.show()
  12. divEls.addClass('active')
  13. divEls.height('100px')
  14. divEls.css('color', 'red')
  15. divEls.on('click', function(e) {
  16. // ...
  17. })

链模式一般会在调用完方法之后返回一个对象,有时则直接返回 this ,
因此又可以继续调用这个对象上的其他方法,这样可以对同一个对象连续执行多个方法

实现链式调用

函数链式调用

让原型方法,都返回该原型的实例对象
所有对象都会继承其原型对象的 prototype上的属性和方法,让原型方法都返回该原型的实例对象,这样就可以对方法进行链式调用

  1. /* 四边形 */
  2. function Rectangle() {
  3. this.length // 长
  4. this.width // 宽
  5. this.color // 颜色
  6. }
  7. /* 设置长度 */
  8. Rectangle.prototype.setLength = function(length) {
  9. this.length = length
  10. return this
  11. }
  12. /* 设置宽度 */
  13. Rectangle.prototype.setWidth = function(width) {
  14. this.width = width
  15. return this
  16. }
  17. /* 设置颜色 */
  18. Rectangle.prototype.setColor = function(color) {
  19. this.color = color
  20. return this
  21. }
  22. var rect = new Rectangle()
  23. .setLength('100px')
  24. .setWidth('80px')
  25. .setColor('blue')
  26. console.log(rect)
  27. // 输出:{length: "100px", width: "80px", color: "blue"}

链式调用练习题

实现一个 human 类,使得他能顺序完成下面的功能

  1. var human = new Human();
  2. human.getUp().cooking().brushing().eat().work();
  3. 要求按顺序输出
  4. 'getUp'
  5. 'cooking'
  6. 'teeth brushing 10s 【此处等待 10 秒'
  7. 'eat 5s 【此处等待 5 秒'
  8. 'work'
  9. class Human {
  10. getUp() {
  11. await console.log('getUp')
  12. }
  13. }

class链式调用

让原型方法,都返回该原型的实例对象

  1. /* 四边形 */
  2. class Rectangle {
  3. constructor() {
  4. this.length // 长 undefined
  5. this.width // 宽
  6. this.color // 颜色
  7. }
  8. /* 设置长度 */
  9. setLength(length) {
  10. this.length = length
  11. return this
  12. }
  13. /* 设置宽度 */
  14. setWidth(width) {
  15. this.width = width
  16. return this
  17. }
  18. /* 设置颜色 */
  19. setColor(color) {
  20. this.color = color
  21. return this
  22. }
  23. }
  24. const rect = new Rectangle()
  25. .setLength('100px')
  26. .setWidth('80px')
  27. .setColor('blue')
  28. console.log(rect)
  29. // 输出:{length: "100px", width: "80px", color: "blue"}
  1. const sendmail = () => new Promise(res => setTimeout(res, 1000));
  2. class Mail {
  3. constructor() {
  4. this.mail = 'mail';
  5. }
  6. attachments(files) {
  7. console.log('adding attachments');
  8. return this;
  9. }
  10. async send() {
  11. console.log('sending...');
  12. return sendmail(this.mail);
  13. }
  14. }
  15. (async() => {
  16. console.log('start');
  17. const files = 'files';
  18. await new Mail().attachments(files).send()
  19. console.log('end');
  20. })();

链式不一定必须返回 this

Promise的then返回一个新的 Promise

Promise 的实现中,每次 then 方法返回的就不是 this,而是一个新的 Promise
我们可以不断 then 下去。后面的每一个 then 都不是从最初的 Promise 实例点出来的,
而是从前一个 then 返回的新的 Promise 实例出来的

  1. const prom1 = new Promise((resolve, reject) => {
  2. setTimeout(() => {
  3. console.log('new promise')
  4. resolve()
  5. }, 500)
  6. })
  7. const prom2 = prom1.then(() => {
  8. console.log('promise then')
  9. })
  10. console.log(prom1 === prom2) // false

$el.end

jquery的方法 end(),将匹配的元素还原为之前一次的状态,返回的也不是 this
返回的之前一次匹配的元素

  1. // 选择所有 p 标签
  2. $("p")
  3. .find("span") // 选择了 p 标签下的 span 标签
  4. .css('color', 'red')
  5. .end() // 返回之前匹配的 p 标签
  6. .css('color', 'blue')

数组的链式调用

因为 filter、map、reduce 这些数组方法返回的仍然是数组,因此可以继续在后面调用数组的方法

  • 并不是所有数组方法都返回数组,比如 push 的时候返回的是新数组的 length 属性
    1. [1, 2, 3, 4, 5, 6]
    2. .filter(num => num % 2)
    3. .map(num => num * num)
    4. .reduce((pre, curr) => pre + curr, 0)

jquery的构造函数

src/core.js

  1. var jQuery = function(selector, context) {
  2. // jQuery 方法返回的是 jQuery.fn.init 所 new 出来的对象
  3. // new 出来的 jQuery.fn.init 实例将继承 jQuery.fn 上的方法
  4. return new jQuery.fn.init(selector, context, rootjQuery)
  5. }
  6. jQuery.fn = jQuery.prototype = {
  7. constructor: jQuery,
  8. // jQuery 对象的构造函数
  9. init: function(selector, context, rootjQuery) {
  10. // ... 一顿匹配操作,返回一个拼装好的伪数组的自身实例
  11. // 是 jQuery.fn.init 的实例,也就是我们常用的 jQuery 对象
  12. return this
  13. },
  14. selector: '',
  15. eq: function() { ... },
  16. end: function() { ... },
  17. map: function() { ... },
  18. last: function() { ... },
  19. first: function() { ... },
  20. // ... 其他方法
  21. }
  22. // jQuery.fn.init 的实例都拥有 jQuery.fn 相应的方法
  23. jQuery.fn.init.prototype = jQuery.fn