Analysis of method chain in JavaScript

Time:2021-6-24

Method chain is a popular programming method, which can help you write more concise and easy to read code. In this article, let’s learn what the method chain in JavaScript is and how it works. In addition, we will explore how to use method links to improve the quality and readability of the code.

Method chain in JavaScript

You must have used libraries like jQuery, and you may have seen something similar. There are mainly two methods for cascading: one is to execute one by one, and the other is to execute on the same line. This is also common in pure JavaScript. You can see it in arrays, strings and promise.

In these cases, all the processes are the same. First, reference the object you want to use. Then use a variety of methods as needed. But instead of using these methods alone, they should be used one by one. It’s basically linking them together. Let’s start with some examples.

Example of method chain

There are two ways to handle strings. The first method does not use a method chain, which requires that each method must be used separately on the string, so that the string must be referenced every time.

The second way is to use method chain. You can use all the string methods you want. The code you write can also be single or multiple lines, depending on your habits. And you only need to refer to the string once. Although the results are the same, the amount of code varies greatly.

//Examples of using method chains on strings
let myStr = ' - Hello-world. '

//No method chain:
myStr = myStr.toLowerCase()
myStr = myStr.replace(/-/g, ' ')
myStr = myStr.trim()

//Method chain:
myStr = myStr.toLowerCase().replace(/-/g, ' ').trim()

//How to write a multiline method chain:
myStr = myStr
  .toLowerCase()
  .replace(/-/g, ' ')
  .trim()

//View the value of "mystr"
console.log(myStr)
// Output:
// 'hello world.'

You can also use method chains on arrays

//Examples of using method chains on arrays
let myArray = [1, 7, 3, null, 8, null, 0, null, '20', 15]

//No method chain:
myArray = myArray.filter(el => typeof el === 'number' && isFinite(el))
myArray = myArray.sort((x, y) => x - y)

//Usage chain:
myArray = myArray.filter(el => typeof el === 'number' && isFinite(el)).sort((x, y) => x - y)

//How to write a multiline method chain:
myArray = myArray
  .filter(el => typeof el === 'number' && isFinite(el))
  .sort((x, y) => x - y)

//View the value of "myArray"
console.log(myArray)
// Output:
// [ 0, 1, 3, 7, 8 ]

Promise is a good example, because it’s almost all method chains when used. First, create a promise, and then add the appropriate handler.

//Create promise
const myPromise = new Promise((resolve, reject) => {
  //Create a false delay
  setTimeout(function() {
    //Solve promise promise with a simple message
    resolve('Sorry, no data.')
  }, 1000)
})

//Usage chain:
myPromise.then((data) => console.log(data)).catch(err => console.log(error))

//How to write a multiline method chain:
myPromise
  .then((data) => console.log(data))
  .catch(err => console.log(error))
// Output:
// 'Sorry, no data.'

How does the method chain work

Next, look at how it works. The answer is simple becausethis

Suppose there is an object. If you use thethis, which refers to the object. If you create an instance or copy of the object, thethisThe instance or copy will be referenced. When you use some string or array methods, you are actually using an object.

const myObj = {
  name: 'Stuart',
  age: 65,
  sayHi() {
    //This is a reference to 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: ƒ
// }

If it is a string, the original data type is used. But the methods you use, for exampletoLowerCase(), existing inStringObject. There is another key element in using method chains on objectsthis

In order for the chain to work, the method must return the object it is used with, that is, it must returnthis. It’s like a baton in a relay race.

Implementing method chain in JavaScript

In order to make the method chain effective, three conditions must be satisfied: first, some objects are needed. Second, the object needs some methods that can be called later. Third, these methods must return the object itself, and they must returnthisTo use the method chain.

Let’s create a simple objectpersonperson yesname, ageandstateProperty.stateUsed to indicate the current state. To change this state, we need to use several methods:walk(), sleep(), eat(), drink(), work()andexercise()

Because we want all of these methods to be chainable, they all have to returnthis. In addition, there is a tool method in the code to record the current status to the console.

//Create person object
const person = {
  name: 'Jack Doer',
  age: 41,
  state: null,
  logState() {
    console.log(this.state)
  },
  drink() {
    //Modify the state of person
    this.state = 'Drinking.'

    //Output status to console
    this.logState()

    //Returns the value of 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.'

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

Method, chain, this and arrow functions

Must usethisIt also means that you cannot create a chain of methods using arrow functions. Because in the arrow function,thisNot bound to an instance of the object, but to a global objectwindowReference to. If you returnthisThen the returned object is not the object itself, but thewindow

Another problem is to access and modify object properties from within arrow functions. becausethisIs a global objectwindow, so it cannot be used to refer to objects and their properties.

If you have to use the arrow function, you have to find a way around it. no needthisTo refer to the object, you must refer to the object directly by its name, that is, replace all the objects that appear in the arrow function with the object namethis

//Create person object
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.'

The disadvantage of this is that it is not flexible. If you useObject.assign()andObject.create()Copy the object, and all arrow functions are still hard wired to the original object.

//Create the original person object
const person = {
  name: 'Jack Doer',
  age: 41,
  state: null,
  logState() {
    //Print the entire object
    console.log(this)
  },
  drink: () => {
    person.state = 'Drinking.'

    person.logState()

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

    person.logState()

    return person
  }
}

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

//Create a new object based on the person object.
const newPerson = new Object(person)

//Modify the "name" and "age" properties
newPerson.name = 'Jackie Holmes'
newPerson.age = 33

//Let newperson drink.
//This will print Jack doer instead of Jackie Holmes.
newPerson.drink()
// Output:
// {
//   name: 'Jack Doer',
//   age: 41,
//   state: 'Drinking.',
//   logState: ƒ,
//   drink: ƒ,
//   eat: ƒ
// }

But if you useObject()Constructor, the above problem will not occur. If you use the sum of the new keywordObject()The construction function will create a new independent object. When you use a method on the new object, it will only work on the new object, not on the original object.

//Create the original person object
const person = {
  name: 'Jack Doer',
  age: 41,
  state: null,
  logState() {
    //Print the entire object
    console.log(this)
  },
  drink: () => {
    person.state = 'Drinking.'

    person.logState()

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

    person.logState()

    return person
  }
}

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

//Create a new object based on person object 
const newPerson = new Object(person)

//Modify the "name" and "age" properties
newPerson.name = 'Jackie Holmes'
newPerson.age = 33

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

If you have to use the arrow function and want to copy objects, you’d better use itObject()Constructors andnewKeyword to create these copies. Otherwise, you just need to use regular functions.

Method chains and classes

If you like to useJavaScript classYou can also use method linking in JavaScript. In addition to the slightly different syntax, the whole process and object are the same. But note that all chainable methods must returnthis

//Create a person class
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
  }
}

//Create a person class的实例
const joe = new Person('Joe', 55)

//Usage chain
joe
  .drink() // Output: 'Drinking.'
  .eat() // Output: 'Eating.'
  .sleep() // Output: 'Sleeping.'

summary

Method chain is very useful, it can help you write shorter, easier to read code.

Analysis of method chain in JavaScript


This article starts with WeChat official account: front-end pioneer.

Welcome to scan the two-dimensional code to pay attention to the official account, and push you every day to send fresh front-end technical articles.

Analysis of method chain in JavaScript


Welcome to continue to read other high praise articles in this column:


Recommended Today

[database] MySQL exercises and answers (educational administration management system)_ MySQL_ 5.7)

✨ statement The answer to the exercise is not guaranteed to be completely correct, which is for reference only MySQL:5.7 Recommended software: Navicat premium Learning SQL statements requires diligent practice! ✨ Field description of each table course CId Course serial number, primary key PCId Prerequisite course DId Opening department number, foreign key CName Course name […]