Làm cách nào để gọi hàm trả về trong JavaScript?

Sẽ rất hữu ích nếu có một chức năng thực hiện một số công việc cho bạn và trả lại cho bạn kết quả của công việc đó. Sau đó, bạn có thể sử dụng kết quả theo cách bạn muốn. Trong danh sách 5. 6 bạn đã thấy hàm showSum hiển thị tổng của hai số trên bảng điều khiển. Có thể tốt hơn nếu có một chức năng thêm chỉ cần thêm các số và trả về kết quả. Trong khi showSum luôn hiển thị kết quả trên bảng điều khiển, với add, bạn có thể hiển thị kết quả mà hàm trả về nếu bạn chọn, sử dụng nó trong các phép tính tiếp theo, gửi qua mạng hoặc lưu vào cơ sở dữ liệu

JavaScript được biết đến rộng rãi vì bản chất cực kỳ linh hoạt của nó. Bài đăng này sẽ hiển thị một số ví dụ về việc tận dụng điều này bằng cách làm việc với các hàm

Vì các hàm có thể được truyền đi khắp mọi nơi, nên chúng ta có thể truyền chúng vào các đối số của hàm

Trải nghiệm thực tế đầu tiên của tôi với bất kỳ thứ gì liên quan đến lập trình nói chung là bắt đầu viết mã bằng JavaScript và một khái niệm trong thực tế khiến tôi bối rối là chuyển các hàm này sang các hàm khác. Tôi đã cố gắng thực hiện một số nội dung "nâng cao" mà tất cả các chuyên gia đang làm nhưng tôi vẫn kết thúc với một số thứ như thế này

function getDate(callback) {
  return callback(new Date())
}

function start(callback) {
  return getDate(callback)
}

start(function (date) {
  console.log(`Todays date: ${date}`)
})

Điều này hoàn toàn lố bịch và thậm chí còn khiến chúng ta khó hiểu hơn tại sao chúng ta lại chuyển các hàm này sang các hàm khác trong thế giới thực, khi chúng ta có thể chỉ cần làm điều này và nhận lại hành vi tương tự

const date = new Date()
console.log(`Todays date: ${date}`)

Nhưng tại sao điều này không đủ tốt cho các tình huống phức tạp hơn?

Sau đó, tôi tiếp tục đặt thêm câu hỏi về các trường hợp sử dụng này và yêu cầu được cung cấp ví dụ về cách sử dụng tốt trên bảng cộng đồng, nhưng không ai muốn giải thích và đưa ra ví dụ

Từ giờ nghĩ lại mới thấy vấn đề là đầu óc mình chưa biết tư duy lập trình. Phải mất một thời gian để tâm trí của bạn chuyển từ cuộc sống ban đầu sang lập trình bằng ngôn ngữ máy tính

Vì tôi hiểu sự thất vọng khi cố gắng hiểu khi nào các hàm bậc cao hơn hữu ích trong JavaScript, nên tôi quyết định viết bài viết này để giải thích từng bước về một trường hợp sử dụng tốt bắt đầu từ một hàm rất cơ bản mà bất kỳ ai cũng có thể viết và phát triển theo cách của chúng tôi.

Chức năng với ý định

Trước tiên, chúng ta sẽ bắt đầu với một chức năng nhằm đạt được mục tiêu cho chúng ta

Làm thế nào về một chức năng sẽ lấy một đối tượng và trả về một đối tượng mới đã cập nhật các kiểu theo cách chúng ta muốn?

Hãy làm việc với đối tượng này (chúng tôi sẽ coi đây là một thành phần)

const component = {
  type: 'label',
  style: {
    height: 250,
    fontSize: 14,
    fontWeight: 'bold',
    textAlign: 'center',
  },
}

Chúng tôi muốn làm cho chức năng của chúng tôi giữ

const date = new Date()
console.log(`Todays date: ${date}`)
1 không ít hơn
const date = new Date()
console.log(`Todays date: ${date}`)
2 và áp dụng một
const date = new Date()
console.log(`Todays date: ${date}`)
3 cho các thành phần nút (các thành phần có
const date = new Date()
console.log(`Todays date: ${date}`)
4) và trả lại cho chúng tôi

Điều này có thể trông giống như thế này

Kết quả

________số 8_______

Giả sử chúng ta nảy ra một ý tưởng rằng mỗi thành phần có thể có nhiều thành phần hơn bên trong nó bằng cách đặt chúng bên trong thuộc tính

const date = new Date()
console.log(`Todays date: ${date}`)
5 của nó. Điều đó có nghĩa là chúng ta phải làm cho cái này xử lý cả các thành phần bên trong

Vì vậy, đưa ra một thành phần như thế này

{
  "type": "div",
  "style": {
    "height": 300,
    "fontSize": 14,
    "fontWeight": "bold",
    "textAlign": "center"
  },
  "children": [
    {
      "type": "input",
      "inputType": "email",
      "placeholder": "Enter your email",
      "style": {
        "border": "1px solid magenta",
        "textTransform": "uppercase"
      }
    }
  ]
}

Chức năng của chúng tôi rõ ràng là không có khả năng hoàn thành công việc, nhưng

Vì gần đây chúng tôi đã thêm khái niệm trẻ em vào các thành phần, nên bây giờ chúng tôi biết có ít nhất hai điều khác nhau đang diễn ra để giải quyết kết quả cuối cùng. Đây là thời điểm tốt để bắt đầu suy nghĩ về sự trừu tượng. Việc trừu tượng hóa các đoạn mã thành các hàm có thể sử dụng lại giúp mã của bạn dễ đọc và dễ bảo trì hơn vì nó ngăn ngừa các tình huống rắc rối như gỡ lỗi một số vấn đề trong chi tiết triển khai của một thứ gì đó

Khi chúng ta trừu tượng hóa các phần nhỏ khỏi một thứ gì đó, bạn cũng nên bắt đầu suy nghĩ về cách ghép các phần này lại với nhau sau đó, chúng ta có thể gọi đó là bố cục

Trừu tượng và Thành phần

Để biết những gì cần trừu tượng hóa, hãy nghĩ về mục tiêu cuối cùng của chúng ta là gì

const date = new Date()
console.log(`Todays date: ${date}`)
6

Về cơ bản, toàn bộ điểm của chức năng này là biến đổi một giá trị thành biểu diễn mà chúng ta mong đợi. Hãy nhớ rằng chức năng ban đầu của chúng tôi là chuyển đổi kiểu của một thành phần nhưng sau đó chúng tôi cũng đã thêm vào các thành phần đó cũng có thể chứa các thành phần bên trong chính chúng bằng thuộc tính

const date = new Date()
console.log(`Todays date: ${date}`)
5 của nó, vì vậy chúng tôi có thể bắt đầu trừu tượng hóa hai phần đó vì rất có thể sẽ có . Vì lợi ích của hướng dẫn này, có thể coi các hàm trừu tượng này là bộ giải quyết

Kết quả

{
  "type": "div",
  "style": {
    "height": 300,
    "fontSize": 14,
    "fontWeight": "bold",
    "textAlign": "center"
  },
  "children": [
    {
      "type": "input",
      "inputType": "email",
      "placeholder": "Enter your email",
      "style": {
        "border": "1px solid magenta",
        "textTransform": "uppercase"
      }
    }
  ]
}

Thay đổi đột phá

Tiếp theo, hãy nói về cách mã này có thể gây ra lỗi nghiêm trọng--lỗi sẽ làm hỏng ứng dụng của bạn

Nếu chúng ta xem xét kỹ các trình giải quyết và xem cách chúng được sử dụng để tính toán kết quả cuối cùng, chúng ta có thể biết rằng nó có thể dễ dàng bị hỏng và khiến ứng dụng của chúng ta gặp sự cố vì hai lý do

  1. Nó biến đổi - Điều gì sẽ xảy ra nếu một lỗi không xác định xảy ra và biến đổi giá trị không chính xác bằng cách gán nhầm giá trị không xác định cho giá trị?

Nếu chúng tôi loại bỏ

const date = new Date()
console.log(`Todays date: ${date}`)
8 từ
const date = new Date()
console.log(`Todays date: ${date}`)
9, chúng tôi ngay lập tức phải đối mặt với
const component = {
  type: 'label',
  style: {
    height: 250,
    fontSize: 14,
    fontWeight: 'bold',
    textAlign: 'center',
  },
}
0 vì đây sẽ trở thành giá trị đến cho chức năng giải quyết tiếp theo

TypeError: Cannot read property 'children' of undefined

  1. Bộ giải quyết ghi đè kết quả trước đó - Đây không phải là một cách làm tốt và đánh bại mục đích trừu tượng hóa.
    const date = new Date()
    console.log(`Todays date: ${date}`)
    9 của chúng tôi có thể tính toán các giá trị của nó nhưng sẽ không thành vấn đề nếu hàm
    const component = {
      type: 'label',
      style: {
        height: 250,
        fontSize: 14,
        fontWeight: 'bold',
        textAlign: 'center',
      },
    }
    2 trả về một giá trị hoàn toàn mới

Giữ mọi thứ bất biến

Chúng ta có thể tiến tới mục tiêu của mình một cách an toàn bằng cách làm cho các hàm này trở nên bất biến và đảm bảo rằng chúng luôn trả về cùng một kết quả nếu được cung cấp cùng một giá trị

Hợp nhất các thay đổi mới

Bên trong hàm

const date = new Date()
console.log(`Todays date: ${date}`)
9 của chúng ta, chúng ta có thể trả về một giá trị (đối tượng) mới chứa các giá trị đã thay đổi mà chúng ta sẽ hợp nhất cùng với giá trị ban đầu. Bằng cách này, chúng tôi có thể đảm bảo rằng các trình phân giải không ghi đè lẫn nhau và việc trả lại
const component = {
  type: 'label',
  style: {
    height: 250,
    fontSize: 14,
    fontWeight: 'bold',
    textAlign: 'center',
  },
}
4 sẽ không có hiệu lực đối với mã khác sau đó

Khi một dự án trở nên lớn hơn

Nếu chúng tôi có 10 trình phân giải kiểu và chỉ có 1 trình phân giải làm việc với trẻ em, việc duy trì có thể trở nên khó khăn, vì vậy chúng tôi có thể chia chúng ra thành phần mà chúng được hợp nhất

Mã gọi các trình phân giải này đã được trừu tượng hóa thành chức năng riêng của nó để chúng tôi có thể sử dụng lại nó và cũng để giảm trùng lặp

Điều gì sẽ xảy ra nếu chúng ta có một trình phân giải cần thêm một số ngữ cảnh để tính toán kết quả của nó?

Ví dụ: điều gì sẽ xảy ra nếu chúng ta có một hàm trình phân giải

const component = {
  type: 'label',
  style: {
    height: 250,
    fontSize: 14,
    fontWeight: 'bold',
    textAlign: 'center',
  },
}
5 đưa vào thuộc tính
const component = {
  type: 'label',
  style: {
    height: 250,
    fontSize: 14,
    fontWeight: 'bold',
    textAlign: 'center',
  },
}
6 khi một số tham số tùy chọn được sử dụng được chuyển vào một nơi nào đó trong trình bao bọc?

Các chức năng cần ngữ cảnh bổ sung

Sẽ thật tuyệt nếu cung cấp cho trình phân giải khả năng nhận ngữ cảnh bổ sung và không chỉ nhận giá trị

const component = {
  type: 'label',
  style: {
    height: 250,
    fontSize: 14,
    fontWeight: 'bold',
    textAlign: 'center',
  },
}
7 làm đối số. Chúng tôi có thể cung cấp khả năng này bằng cách sử dụng tham số thứ hai của các hàm trình phân giải của chúng tôi, nhưng tôi nghĩ rằng các tham số đó nên được lưu cho các trừu tượng cấp thấp hơn trên cơ sở cấp thành phần

Điều gì sẽ xảy ra nếu trình phân giải có khả năng trả về một hàm và nhận ngữ cảnh mà chúng cần từ các đối số của hàm được trả về?

Một cái gì đó trông như thế này

function resolveTimestampInjection(component) {
  return function ({ displayTimestamp }) {
    if (displayTimestamp === true) {
      return {
        time: new Date(currentDate).toLocaleTimeString(),
      }
    }
  }
}

Sẽ thật tuyệt nếu chúng ta có thể kích hoạt chức năng này mà không thay đổi hành vi của mã gốc

Đây là lúc sức mạnh tổng hợp các hàm bậc cao bắt đầu tỏa sáng và tin tốt là chúng rất dễ thực hiện

Trừu tượng hóa những điều trừu tượng

Để kích hoạt chức năng này, hãy di chuyển một bước cao hơn trong phần trừu tượng hóa bằng cách gói các trình phân giải vào một hàm bậc cao hơn chịu trách nhiệm đưa ngữ cảnh vào các hàm trình phân giải cấp thấp hơn

Giờ đây, chúng ta có thể trả về một hàm từ bất kỳ hàm nào mà chúng ta đăng ký làm trình phân giải và vẫn duy trì hoạt động của ứng dụng như cũ, như vậy

const getBaseStyles = () => ({ baseStyles: { color: '#333' } })
const baseStyles = getBaseStyles()

const injectContext = makeInjectContext({
  baseStyles,
})

function resolveTimestampInjection(component) {
  return function ({ displayTimestamp }) {
    if (displayTimestamp === true) {
      return {
        time: new Date(currentDate).toLocaleTimeString(),
      }
    }
  }
}

Trước khi tôi đưa ra ví dụ cuối cùng, hãy xem qua hàm bậc cao hơn của

const component = {
  type: 'label',
  style: {
    height: 250,
    fontSize: 14,
    fontWeight: 'bold',
    textAlign: 'center',
  },
}
8 và tìm hiểu xem nó đang làm gì

Đầu tiên, nó nhận một đối tượng mà bạn muốn được chuyển đến tất cả các hàm của trình phân giải và trả về một hàm nhận hàm gọi lại làm đối số. Tham số gọi lại này sau này sẽ trở thành một trong các hàm trình phân giải ban đầu. Lý do tại sao chúng tôi làm điều này là bởi vì chúng tôi đang làm những gì được gọi là gói. Chúng tôi đã bao hàm cuộc gọi lại bằng một chức năng bên ngoài để chúng tôi có thể thêm chức năng bổ sung trong khi vẫn duy trì hoạt động của chức năng ban đầu bằng cách đảm bảo rằng chúng tôi gọi cuộc gọi lại bên trong tại đây. Nếu kiểu trả về của kết quả của cuộc gọi lại là một hàm, chúng tôi sẽ cho rằng cuộc gọi lại đó cần ngữ cảnh, vì vậy chúng tôi gọi kết quả của cuộc gọi lại một lần nữa--và đó là nơi chúng tôi chuyển vào ngữ cảnh

Khi chúng tôi gọi cuộc gọi lại đó (một chức năng được cung cấp bởi người gọi) và thực hiện một số tính toán bên trong hàm trình bao bọc, chúng tôi có các giá trị đến từ trình bao bọc và từ trình gọi. Đây là một trường hợp sử dụng tốt cho mục tiêu cuối cùng của chúng tôi vì chúng tôi muốn hợp nhất các kết quả lại với nhau thay vì cho phép mỗi hàm trình phân giải có khả năng ghi đè một giá trị hoặc kết quả từ hàm trình phân giải trước đó. Việc có các trường hợp sử dụng nâng cao khác để giải quyết các vấn đề khác nhau cũng chẳng có ích gì và đây là một ví dụ điển hình để giới thiệu một tình huống mà chúng tôi cần chiến lược phù hợp để sử dụng cho tình huống phù hợp--vì nếu giống tôi, bạn có thể đã thử

Làm cách nào để gọi hàm JavaScript có giá trị trả về?

Gọi hàm JavaScript có giá trị trả về . Chỉ cần gọi nó theo cùng một cách, bạn sẽ chỉ cần bỏ qua giá trị trả về và tiếp tục. Nếu bạn cần nắm bắt giá trị trả về từ hàm, thì bạn có thể gán kết quả đó cho một biến. using the same method as any other function. By just calling it the same way, you will simply ignore the return value, and move on. If you need to capture the return value from the function, then you can assign it's result to a variable.

Làm cách nào để sử dụng return trong hàm JavaScript?

Khi một câu lệnh trả về được sử dụng trong thân hàm, việc thực thi hàm sẽ bị dừng . Nếu được chỉ định, một giá trị đã cho sẽ được trả về cho người gọi hàm. Ví dụ: hàm sau đây trả về bình phương của đối số của nó, x , trong đó x là một số. Nếu giá trị bị bỏ qua, thay vào đó, undefined được trả về.

Chúng ta có thể gọi một hàm trong câu lệnh return không?

Câu lệnh return kết thúc quá trình thực thi hàm và trả lại quyền điều khiển cho hàm gọi . Thực thi tiếp tục trong chức năng gọi tại thời điểm ngay sau cuộc gọi. Một câu lệnh return có thể trả về một giá trị cho hàm gọi.