6 Functions for the journeyman: understanding function invocation
This chapter explains how JavaScript functions receive an implicit this value, called the function context, and why that context depends on invocation style rather than just where a function is defined. It begins by showing that methods in classes commonly use this to access instance state, but that the same function can behave very differently if it is assigned to a variable or passed around without its original object. In strict mode, standalone function calls usually get undefined as this, which helps surface mistakes earlier instead of silently falling back to the global object.
The chapter then compares the major ways to invoke functions in JavaScript: as standalone functions, as object methods, as constructors with new, and through call or apply. Each form sets this differently, and this difference explains both the flexibility and the confusion surrounding function context. Constructors create a fresh object, pass it in as this, and normally return it automatically; call and apply let you explicitly choose the context, with the only real difference being whether arguments are supplied individually or as an array.
Finally, the chapter focuses on practical ways to avoid context-related bugs, especially when functions are used as callbacks. It shows how bind creates a new function with permanently fixed this, making unbound methods safe to pass around, and how arrow functions sidestep the problem by capturing this lexically from the surrounding scope. The chapter closes by emphasizing that these tools make code more predictable, while also warning about common pitfalls such as assuming ordinary objects create lexical context or treating all functions as constructors.
When calling a function with new, a new empty object is created and set as the context of the constructor function, the this parameter.
As the first argument, both the call and apply methods take the object that will be used as the function context. The difference is in the following arguments. apply takes only one additional argument, an array of argument values; call takes any number of arguments, which will be used as function arguments.
Summary
- The this keyword is an implicit function parameter that represents context in which the function was invoked. How this is determined can depend on the way a function is defined as well as on how it’s invoked.
- Arrow functions always have the same value of this as their surrounding context, regardless of how they’re invoked.
- Class fields are a special type of arrow function that’s permanently bound to a class instance.
- A function can be invoked in four ways:
- As a standalone function: skulk()
- As a method: ninja.skulk()
- As a constructor: new Ninja()
- Via its apply and call methods: skulk.call(ninja) or skulk.apply(ninja)
- The way a function is invoked influences the value of the this parameter:
- If a non-arrow function is invoked as a function, the value of this is undefined (assuming you’re in strict mode).
- If a non-arrow function is invoked as a method, the value of this is usually the object on which the function was invoked.
- If a non-arrow function is invoked as a constructor, the value of this is the newly constructed object.
- If a non-arrow function is invoked through call and apply, the value of this is the first argument supplied to call and apply.
- You can use the bind method to create a new function that’s always bound to the argument of the bind method (unless it’s an arrow function, in which case the new function will be identical to the original in every way).
FAQ
What is the role of the implicit this parameter in JavaScript function invocation?
this is an implicit parameter passed to a function when it is invoked. It refers to the object associated with that invocation and is often called the function context.
How does a function’s invocation style affect the value of this?
The invocation style determines the function context. A standalone call usually gives this as undefined in strict mode, a method call sets it to the owning object, new sets it to a newly created object, and call/apply let you choose it explicitly.
What happens when a function is invoked as a standalone function?
If a non-arrow function is called on its own, this is typically undefined in strict mode. If strict mode is off, this becomes the global object.
What makes a function invocation a method call?
A function is invoked as a method when it is stored as a property of an object and called through that property, such as obj.method(). In that case, the object becomes this.
Why can assigning a method to a variable break its behavior?
Because the method loses the object it was called on. Once extracted, it becomes an unbound method, so when invoked later it no longer receives the original object as this.
What does the new keyword do when calling a function?
new creates a fresh empty object, passes it into the function as this, and returns that object unless the constructor explicitly returns a different object.
How do call and apply differ?
Both invoke a function with an explicitly supplied this value. The difference is that apply takes the function arguments as an array, while call takes them as individual arguments.
What does bind do to a function?
bind does not run the function immediately. It returns a new function whose this is permanently bound to a chosen object, no matter how the new function is later invoked.
How do arrow functions handle this differently from ordinary functions?
Arrow functions do not have their own this. Instead, they use lexical this, meaning they inherit this from the surrounding scope and ignore attempts to change it with call, apply, or bind.
What happens if a constructor explicitly returns a value?
If it returns an object, that object replaces the usual constructor result. If it returns a primitive, the return value is ignored and the constructed this object is returned instead.
Secrets of the JavaScript Ninja, Third Edition ebook for free