Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >浅析 JavaScript 中的方法链

浅析 JavaScript 中的方法链

作者头像
疯狂的技术宅
发布于 2021-02-25 08:26:44
发布于 2021-02-25 08:26:44
62703
代码可运行
举报
文章被收录于专栏:京程一灯京程一灯
运行总次数:3
代码可运行
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

方法链是一种流行的编程方法,可以帮助你写出更简洁易读的代码。在本文中我们一起学习 JavaScript 中的方法链是什么,以及它是怎样工作的。另外我们还会探讨如何使用方法链接来提高代码的质量和可读性。

JavaScript 中方法链

你一定曾经用过 jQuery 之类的库,可能看到过类似的东西。在进行级联时主要有两种方法:一种是一个接一个的执行方法,另一种是在同一行上。在纯 JavaScript 中这种做法也很普遍。你可以在数组、字符串和 promise 看到它。

在这些情况下所有的过程都是相同的。首先引用要使用的对象。然后根据需要使用多种方法。但不是单独使用这些方法,而要一个接一个地使用。基本上是把它们链接在一起。先看一些例子。

方法链的例子

在处理字符串时有两种方法。第一个种不用方法链,这要求必须在字符串上分别使用每个方法,这样必须每次都引用这个字符串。

第二种方式是用方法链。这时可以用所有想要的字符串方法。写出的代码也可以是单行或多行,这取决于你的习惯。而且只需要引用一次字符串。尽管结果相同,但是代码量却有很大的差异。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 在字符串上使用方法链的例子
let myStr = ' - Hello-world. '

// 不用方法链:
myStr = myStr.toLowerCase()
myStr = myStr.replace(/-/g, ' ')
myStr = myStr.trim()

// 用方法链:
myStr = myStr.toLowerCase().replace(/-/g, ' ').trim()

// 多行方法链的写法:
myStr = myStr
  .toLowerCase()
  .replace(/-/g, ' ')
  .trim()

// 查看 "myStr" 的值
console.log(myStr)
// Output:
// 'hello world.'

在数组上也能用方法链:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 在数组上使用方法链的例子
let myArray = [1, 7, 3, null, 8, null, 0, null, '20', 15]

// 不用方法链:
myArray = myArray.filter(el => typeof el === 'number' && isFinite(el))
myArray = myArray.sort((x, y) => x - y)

// 使用方法链:
myArray = myArray.filter(el => typeof el === 'number' && isFinite(el)).sort((x, y) => x - y)

// 多行方法链的写法:
myArray = myArray
  .filter(el => typeof el === 'number' && isFinite(el))
  .sort((x, y) => x - y)

// 查看 "myArray" 的值.
console.log(myArray)
// Output:
// [ 0, 1, 3, 7, 8 ]

Promise 是一个很好的例子,因为在使用时差不多全都是方法链。首先创建一个 promise,然后添加适当的处理函数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建 Promise
const myPromise = new Promise((resolve, reject) => {
  // 创建一个假延迟
  setTimeout(function() {
    // 用一条简单的消息解决诺言 promise
    resolve('Sorry, no data.')
  }, 1000)
})

// 使用方法链:
myPromise.then((data) => console.log(data)).catch(err => console.log(error))

// 多行方法链的写法:
myPromise
  .then((data) => console.log(data))
  .catch(err => console.log(error))
// Output:
// 'Sorry, no data.'

方法链是怎样工作的

接下来研究它是怎样工作的。答案很简单,是因为 this

假设有一个对象。如果在该对象内使用 this,它会引用这个对象。如果创建该对象的实例或副本,则 this 将会引用这个实例或副本。当你使用某些字符串或数组方法时,实际上是在用一个对象。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const myObj = {
  name: 'Stuart',
  age: 65,
  sayHi() {
    // 这里的 this 是 myObj 的引用
    return `Hi my name is ${this.name}.`
  },
  logMe() {
    console.log(this)
  }
}

myObj.sayHi()
// Output:
// 'Hi my name is Stuart.'

myObj.logMe()
// Output:
// {
//   name: 'Stuart',
//   age: 65,
//   sayHi: ƒ,
//   logMe: ƒ
// }

如果是字符串,则使用的是原始数据类型。但是你所使用的方法例如 toLowerCase(),存在于 String 对象的原型中。在对象上使用方法链还有一个关键要素:this

为了使链起作用,方法必须返回与其一起使用的对象,也就是必须返回 this。就像接力赛跑时的接力棒一样。

在 JavaScript 中实现方法链

为了使方法链有效,必须满足三个条件:首先,需要一些对象。其次,该对象需要一些以后可以调用的方法。第三,这些方法必须返回对象本身,它们必须返回 this 才能使用方法链。

让我们创建一个简单的对象 personpersonname, agestate 属性。state 用来表示当前处于什么状态。要想改变这个状态,需要用到几个方法:walk(), sleep(), eat(), drink(), work()exercise()

由于我们希望所有这些方法都是可链的,所以它们都必须返回 this。另外代码中还有一个用来把当前状态记录到控制台的工具方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建 person 对象
const person = {
  name: 'Jack Doer',
  age: 41,
  state: null,
  logState() {
    console.log(this.state)
  },
  drink() {
    // 修改 person 的 state.
    this.state = 'Drinking.'

    // 把状态输出到控制台
    this.logState()

    // 返回 this 值。
    return this
  },
  eat() {
    this.state = 'Eating.'
    this.logState()
    return this
  },
  exercise() {
    this.state = 'Exercising.'
    this.logState()
    return this
  },
  sleep() {
    this.state = 'Sleeping.'
    this.logState()
    return this
  },
  walk() {
    this.state = 'Walking.'
    this.logState()
    return this
  },
  work() {
    this.state = 'Working.'
    this.logState()
    return this
  }
}

// 
person
  .drink() // Output: 'Drinking.'
  .exercise() // Output: 'Exercising.'
  .eat() // Output: 'Eating.'
  .work() // Output: 'Working.'
  .walk() // Output: 'Walking.'
  .sleep() // Output: 'Sleeping.'

// 写在一行上
person.drink().exercise().eat().work().walk().sleep()
// Output:
// 'Drinking.'
// 'Exercising.'
// 'Eating.'
// 'Working.'
// 'Walking.'
// 'Sleeping.'

方法、链、this 和箭头函数

必须使用 this 也意味着无法使用箭头函数创建方法链。因为在箭头函数中,this 没有绑定到对象的实例,而是全局对象 window 的引用。如果返回 this,那么返回的不是对象本身而是 window

另一个问题是从箭头函数内部访问和修改对象属性。由于 this 是全局对象 window,所以不能用它来引用对象及其属性。

如果你一定要使用箭头函数,必须想办法绕过这种方法。不用 this 来引用该对象,必须直接通过其名称引用该对象,也就是用对象名替换所有出现在箭头功能内的 this

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建 person 对象
const person = {
  name: 'Jack Doer',
  age: 41,
  state: null,
  logState() {
    console.log(this.state)
  },
  drink: () => {
    person.state = 'Drinking.'

    person.logState()

    return person
  },
  eat: () => {
    person.state = 'Eating.'

    person.logState()

    return person
  },
  exercise: () => {
    person.state = 'Exercising.'

    person.logState()

    return person
  },
  sleep: () => {
    person.state = 'Sleeping.'

    person.logState()

    return person
  },
  walk: () => {
    person.state = 'Walking.'

    person.logState()

    return person
  },
  work: () => {
    person.state = 'Working.'

    person.logState()

    return person
  }
}

// 
person
  .drink() // Output: 'Drinking.'
  .exercise() // Output: 'Exercising.'
  .eat() // Output: 'Eating.'
  .work() // Output: 'Working.'
  .walk() // Output: 'Walking.'
  .sleep() // Output: 'Sleeping.'

这样做的缺点是灵活性不好。如果如果用Object.assign() 和 Object.create()复制对象,所有箭头函数仍然会硬连接到原始对象。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建原始 person 对象
const person = {
  name: 'Jack Doer',
  age: 41,
  state: null,
  logState() {
    // 打印整个对象
    console.log(this)
  },
  drink: () => {
    person.state = 'Drinking.'

    person.logState()

    return person
  },
  eat: () => {
    person.state = 'Eating.'

    person.logState()

    return person
  }
}

// 让 person eat
person.eat()
// Output:
// {
//   name: 'Jack Doer',
//   age: 41,
//   state: 'Eating.',
//   logState: ƒ,
//   drink: ƒ,
//   eat: ƒ
// }

// 基于person对象创建新对象。
const newPerson = new Object(person)

// 修改 "name" 和 "age" 属性
newPerson.name = 'Jackie Holmes'
newPerson.age = 33

// 让 newPerson drink。
// 这会打印 Jack Doer 而不是 Jackie Holmes。
newPerson.drink()
// Output:
// {
//   name: 'Jack Doer',
//   age: 41,
//   state: 'Drinking.',
//   logState: ƒ,
//   drink: ƒ,
//   eat: ƒ
// }

但是,如果用 Object() 构造函数,就不会发生上述问题。如果用 new 关键字的和 Object() 构造造函数,将会创建独立的新对象。当你对这个新对象使用某个方法时,它将仅对这个新对象有效,而对原始对象无效。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建原始 person 对象
const person = {
  name: 'Jack Doer',
  age: 41,
  state: null,
  logState() {
    // 打印整个对象
    console.log(this)
  },
  drink: () => {
    person.state = 'Drinking.'

    person.logState()

    return person
  },
  eat: () => {
    person.state = 'Eating.'

    person.logState()

    return person
  }
}

// 让 person eat.
person.eat()
// Output:
// {
//   name: 'Jack Doer',
//   age: 41,
//   state: 'Eating.',
//   logState: ƒ,
//   drink: ƒ,
//   eat: ƒ
// }

// 基于 person 对象创建新对象 
const newPerson = new Object(person)

// 修改 "name" 和 "age" 属性
newPerson.name = 'Jackie Holmes'
newPerson.age = 33

// 让 newPerson drink.
newPerson.drink()
// Output:
// {
//   name: 'Jackie Holmes',
//   age: 33,
//   state: 'Drinking.',
//   logState: ƒ,
//   drink: ƒ,
//   eat: ƒ
// }

如果你一定要用箭头功能,并想要复制对象的话,最好用 Object() 构造函数和 new 关键字创建这些副本。否则只需要用常规函数就够了。

方法链和类

如果你喜欢使用 JavaScript 类,也可以在JavaScript中使用方法链接。除了语法略又不同外,整个过程和对象是一样的。但是要注意所有可链的方法都必须返回 this

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建 Person 类
class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
    this.state = null
  }

  logState() {
    console.log(this.state)
  }

  drink() {
    this.state = 'Drinking.'

    this.logState()

    return this
  }

  eat() {
    this.state = 'Eating.'

    this.logState()

    return this
  }

  sleep() {
    this.state = 'Sleeping.'

    this.logState()

    return this
  }
}

// 创建 Person 类的实例
const joe = new Person('Joe', 55)

// 使用方法链
joe
  .drink() // Output: 'Drinking.'
  .eat() // Output: 'Eating.'
  .sleep() // Output: 'Sleeping.'

总结

方法链是非常有用的,它可以帮你编写更短、更易读的代码。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-02-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端先锋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JavaScript 原型的深入指南
不学会怎么处理对象,你在 JavaScript 道路就就走不了多远。它们几乎是 JavaScript 编程语言每个方面的基础。事实上,学习如何创建对象可能是你刚开始学习的第一件事。
前端小智@大迁世界
2019/05/13
1.2K0
JavaScript 原型的深入指南
解释JavaScript中的原型链
在JavaScript中,原型链是实现对象继承的核心机制。通过原型链,JavaScript能够让对象共享属性和方法,从而实现代码的重用和更灵活的对象模型。本文将详细探讨原型链的概念、机制、使用以及在实际开发中的应用。
王小婷
2025/05/25
880
JavaScript原型-进阶者指南
它们几乎是JavaScript编程语言的每个方面的基础。在这篇文章中,将了解用于实例化新对象的各种模式,并且这样做,将逐渐深入了解JavaScript的原型。
一墨编程学习
2019/01/07
1.3K0
JAVASCRIPT OBJECTS
ECMAscript 说明文档对这门语言的定义是“一门适于在宿主环境中执行计算及操作计算对象的面向对象的编程语言”。简单的说,JavaScript是一门面向对象(OO)的语言。
政采云前端团队
2019/12/20
6190
JavaScript中的类(ES5+ES6)
ECMAScript 2015 中引入的 JavaScript 类实质上是 JavaScript 现有的基于原型的继承的语法糖。类语法不会为JavaScript引入新的面向对象的继承模型。
刘亦枫
2020/03/19
9930
ES6 class介绍
ES6的class是基于原型继承的一种封装方式。它使用了构造函数和原型链的概念来创建和继承对象。通过class,我们可以定义一个类,然后使用该类来创建具有相同属性和方法的对象实例。
堕落飞鸟
2023/05/23
2690
今天你学C++了吗?——C++中的继承
继承?什么是继承?在生活中,我们可以听到继承人这样的专有名词,那么C++中的继承是什么呢?我们来看看继承的概念~
用户11352420
2025/03/13
1640
今天你学C++了吗?——C++中的继承
this 指向2 — 类中的this
this 在 类 中的表现与在函数中类似,因为类本质上也是函数,但也有一些区别和注意事项。
用户9914333
2022/07/22
3030
this 指向2 —  类中的this
熬夜7天,我总结了JavaScript与ES的25个重要知识点!
说起JavaScript,大家都知道是一门脚本语言。那么ES是什么鬼呢?ES全称ECMAScript ,是JavaScript语言的国际标准。
达达前端
2020/09/17
1.8K0
熬夜7天,我总结了JavaScript与ES的25个重要知识点!
对Javascript 类、原型链、继承的理解
  和其他面向对象的语言(如Java)不同,Javascript语言对类的实现和继承的实现没有标准的定义,而是将这些交给了程序员,让程序员更加灵活地(当然刚开始也更加头疼)去定义类,实现继承。(以下不讨论ES6中利用class、extends关键字来实现类和继承;实质上,ES6中的class、extends关键字是利用语法糖实现的)
smy
2019/02/13
7200
对Javascript 类、原型链、继承的理解
这样回答前端面试题才能拿到offer2
Webkit 和 Firefox 都做了这个优化,当执行 JavaScript 脚本时,另一个线程解析剩下的文档,并加载后面需要通过网络加载的资源。这种方式可以使资源并行加载从而使整体速度更快。需要注意的是,预解析并不改变 DOM 树,它将这个工作留给主解析过程,自己只解析外部资源的引用,比如外部脚本、样式表及图片。
loveX001
2023/01/04
5000
【一起来烧脑】一步学会TypeScript入门
字符串新特性 变量和参数新特性 函数新特性 匿名函数 for of循环 TypeScript语言中的面向对象特性
达达前端
2019/07/18
4810
【一起来烧脑】一步学会TypeScript入门
React 组件优化方案
如果你知道在什么情况下你的组件不需要更新,你可以在 shouldComponentUpdate 中返回 false 来跳过整个渲染过程。其包括该组件的 render 调用以及之后的操作。该方法会在 重新渲染前 被触发,其默认实现总是返回 true。
多云转晴
2020/02/17
3.3K0
JavaScript 进阶教程(3)---让你彻底搞懂原型链和继承
关于原型在JavaScript 进阶教程(1)--面向对象编程这篇文章已经讲过了,今天简单来复习一下。
AlbertYang
2020/09/08
5360
JavaScript 进阶教程(3)---让你彻底搞懂原型链和继承
一篇JavaScript技术栈带你了解继承和原型链
在学习JavaScript中,我们知道它是一种灵活的语言,具有面向对象,函数式风格的编程模式,面向对象具有两点要记住,三大特性,六大原则。
达达前端
2019/11/19
4730
全面理解面向对象的 JavaScript
前言 当今 JavaScript 大行其道,各种应用对其依赖日深。web 程序员已逐渐习惯使用各种优秀的 JavaScript 框架快速开发 Web 应用,从而忽略了对原生 JavaScript 的学习和深入理解。所以,经常出现的情况是,很多做了多年 JS 开发的程序员对闭包、函数式编程、原型总是说不清道不明,即使使用了框架,其代码组织也非常糟糕。这都是对原生 JavaScript 语言特性理解不够的表现。要掌握好 JavaScript,首先一点是必须摒弃一些其他高级语言如 Java、C# 等类式面向对象思
庞小明
2018/03/07
1.1K0
全面理解面向对象的 JavaScript
面向对象进阶 | 深入探究 Java 静态成员与继承体系
Javabean类:用来描述一类事物的类。比如:Student、Teather、Dog等
钮祜禄.爱因斯晨
2025/06/11
880
面向对象进阶 | 深入探究 Java 静态成员与继承体系
【JS 口袋书】第 5 章:JS 对象生命周期的秘密
咱们经常听到JS中“一切皆对象”? 有没有问想过这是什么意思? 其它语言也有“一切皆对象”之说,如Python。 但是Python中的对象不仅仅是像JS对象这样的存放值和值的容器。 Python中的对象是一个类。 JS中有类似的东西,但JS中的“对象”只是键和值的容器:
前端小智@大迁世界
2019/10/14
1.7K0
【JS 口袋书】第 5 章:JS 对象生命周期的秘密
JavaScript原型链污染原理及相关CVE漏洞剖析
2019年初,Snyk的安全研究人员披露了流行的JavaScript库Lodash中一个严重漏洞的详细信息,该漏洞使黑客能够攻击多个Web应用程序,这个安全漏洞就是一个“原型污染漏洞”(JavaScript Prototype Pollution),攻击者可以利用该漏洞利用JavaScript编程语言的规则并以各种方式破坏应用程序。
FB客服
2021/07/02
4.4K0
有个开发者总结这 15 优雅的 JavaScript 个技巧
JavaScript 有很多很酷的特性,大多数初学者和中级开发人员都不知道。今天分享一些,我经常在项目中使用一些技巧。
前端小智@大迁世界
2022/06/15
7450
有个开发者总结这 15 优雅的 JavaScript 个技巧
相关推荐
JavaScript 原型的深入指南
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验