Skip to content

Commit

Permalink
Consolidate bind snippets
Browse files Browse the repository at this point in the history
  • Loading branch information
Chalarangelo committed Feb 24, 2024
1 parent 8e5d190 commit 87686e1
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 132 deletions.
42 changes: 27 additions & 15 deletions content/redirects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -337,9 +337,6 @@
- from: /articles/s/javascript-for-loop-early-break
to: /js/s/for-loop-early-break
status: 301!
- from: /articles/s/javascript-function-call-apply-bind
to: /js/s/function-call-apply-bind
status: 301!
- from: /articles/s/javascript-generator-for-range
to: /js/s/generator-for-range
status: 301!
Expand Down Expand Up @@ -934,15 +931,6 @@
- from: /js/s/attempt
to: /js/s/attempt-invoking-function
status: 301!
- from: /js/s/bind
to: /js/s/bind-function-context
status: 301!
- from: /js/s/bind-key
to: /js/s/bind-object-method
status: 301!
- from: /js/s/call
to: /js/s/call-functions-with-context
status: 301!
- from: /js/s/initialize2-d-array
to: /js/s/initialize-2d-array
status: 301!
Expand Down Expand Up @@ -976,9 +964,6 @@
- from: /js/s/debounce
to: /js/s/debounce-function
status: 301!
- from: /js/s/bind-all
to: /js/s/bind-object-methods
status: 301!
- from: /js/s/copy-sign
to: /js/s/copy-sign-to-number
status: 301!
Expand Down Expand Up @@ -2665,3 +2650,30 @@
- from: /js/s/transform-object
to: /js/s/transform-object-keys
status: 301!
- from: /js/s/bind
to: /js/s/function-call-apply-bind
status: 301!
- from: /js/s/bind-function-context
to: /js/s/function-call-apply-bind
status: 301!
- from: /js/s/bind-key
to: /js/s/function-call-apply-bind
status: 301!
- from: /js/s/bind-object-method
to: /js/s/function-call-apply-bind
status: 301!
- from: /js/s/bind-all
to: /js/s/function-call-apply-bind
status: 301!
- from: /js/s/bind-object-methods
to: /js/s/function-call-apply-bind
status: 301!
- from: /js/s/call
to: /js/s/function-call-apply-bind
status: 301!
- from: /js/s/call-functions-with-context
to: /js/s/function-call-apply-bind
status: 301!
- from: /articles/s/javascript-function-call-apply-bind
to: /js/s/function-call-apply-bind
status: 301!
25 changes: 0 additions & 25 deletions content/snippets/js/s/bind-function-context.md

This file was deleted.

28 changes: 0 additions & 28 deletions content/snippets/js/s/bind-object-method.md

This file was deleted.

35 changes: 0 additions & 35 deletions content/snippets/js/s/bind-object-methods.md

This file was deleted.

24 changes: 0 additions & 24 deletions content/snippets/js/s/call-functions-with-context.md

This file was deleted.

80 changes: 75 additions & 5 deletions content/snippets/js/s/function-call-apply-bind.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
---
title: JavaScript function methods - call(), apply() and bind()
shortTitle: Function methods - call(), apply() and bind()
shortTitle: Function methods - call, apply, bind
type: story
language: javascript
tags: [function]
cover: canoe
excerpt: Learn everything you need to know about JavaScript's `call()`, `apply()` and `bind()` in this short guide.
dateModified: 2021-06-12
dateModified: 2024-02-20
---

Developers often confuse `Function.prototype.call()`, `Function.prototype.apply()` and `Function.prototype.bind()`. While these three methods are similar, they have different use cases and behaviors. Apart from learning how they work and when to use each one, we'll also look at some practical examples to help you understand them better.

## Function methods

JavaScript functions are **first-class objects**, which means they can be passed around like any other object. They can also have properties and methods, and can be passed as arguments to other functions. The `Function` object has several methods, including `call()`, `apply()` and `bind()`, which are used to set the `this` value and pass arguments to a function.

## Function.prototype.call()

`Function.prototype.call()` is used to call a function with a given `this` context and any arguments provided individually. For example:
`Function.prototype.call()` is used to call a function with a given `this` context and any arguments provided **individually**. For example:

```js
function printThisAndData(...data) {
Expand All @@ -27,7 +33,7 @@ printThisAndData.call(obj, ...data); // logs: 0 1 2 3

## Function.prototype.apply()

`Function.prototype.apply()` is almost identical to `Function.prototype.call()` in the sense that it calls a function with a given `this` context, however it requires arguments to be provided as an array. For example:
`Function.prototype.apply()` is almost identical to `Function.prototype.call()` in the sense that it calls a function with a given `this` context, however it requires arguments to be provided as an **array**. For example:

```js
function printThisAndData(...data) {
Expand All @@ -43,7 +49,7 @@ printThisAndData.apply(obj, ...data); // Throws a TypeError

## Function.prototype.bind()

`Function.prototype.bind()` is slightly different from the previous two methods. Instead of calling a function with the given `this` context and returning the result, it returns a function with its `this` context bound and any arguments provided individually prepended to the arguments at the time of calling the returned function. For example:
`Function.prototype.bind()` is slightly different from the previous two methods. Instead of calling a function with the given `this` context and returning the result, it returns a function with its `this` context bound and any arguments provided individually **prepended** to the arguments at the time of calling the returned function. For example:

```js
function printThisAndData(...data) {
Expand All @@ -63,3 +69,67 @@ const printObjTwoAndData = printThisAndData.bind(obj, 2);
printObjTwoAndData(data); // logs: 0 2 [1, 2, 3]
printObjTwoAndData(...data); // logs: 0 2 1 2 3
```

## Using function methods in practice

Knowing how these methods work is fine, but where would you use them in real life? Some examples include binding a method to an object, calling a function with a specific context, or calling a function with a specific set of arguments.

### Bind a method to an object

You can use `Function.prototype.apply()` to create a function that invokes the method at a **given key** of an object, optionally prepending any additional supplied parameters to the arguments.

```js
const bindKey = (context, fn, ...boundArgs) => (...args) =>
context[fn].apply(context, [...boundArgs, ...args]);

const freddy = {
user: 'fred',
greet: function(greeting, punctuation) {
return greeting + ' ' + this.user + punctuation;
}
};
const freddyBound = bindKey(freddy, 'greet');
console.log(freddyBound('hi', '!')); // 'hi fred!'
```

### Bind all object methods

Similarly, you can bind **all methods** of an object to the object itself, overwriting the existing method. The technique is the same as before, but you need to use `Array.prototype.forEach()` to iterate over the given methods.

```js
const bindAll = (obj, ...fns) =>
fns.forEach(
fn => (
(f = obj[fn]),
(obj[fn] = function() {
return f.apply(obj);
})
)
);

let view = {
label: 'docs',
click: function() {
console.log('clicked ' + this.label);
}
};
bindAll(view, 'click');
document.body.addEventListener('click', view.click);
// Log 'clicked docs' when clicked.
```

### Bind function context

You can also create a function that invokes a given function with a **specific context**, optionally prepending any additional supplied parameters to the arguments. Same as before, use `Function.prototype.apply()` to apply the given context to the function.

```js
const bind = (fn, context, ...boundArgs) => (...args) =>
fn.apply(context, [...boundArgs, ...args]);

function greet(greeting, punctuation) {
return greeting + ' ' + this.user + punctuation;
}
const freddy = { user: 'fred' };
const freddyBound = bind(greet, freddy);
console.log(freddyBound('hi', '!')); // 'hi fred!'
```

0 comments on commit 87686e1

Please sign in to comment.