While working with JavaScript, it's important to understand the concept of hoisting. Var
variables are hoisted to the top, but their initializations do not move along. On the other hand, functions
and their definitions are also hoisted. Relying heavily on hoisting in your code can lead to potential issues.
Let's visualize how hoisting works in your original functioning code:
// 👇 HOISTED DECLARATIONS
var dataObj = undefined;
function dataFunction (){
return dataObj
}
var methodsObj = undefined;
function methodImpl (){
this.title = 'Infinite Jest'
}
// 👆 HOISTED DECLARATIONS
const app = Vue.createApp({
data: dataFunction,
methods: {method1: methodImpl} // ✅ methodImpl is declared above
})
// INITIALIZATION
dataObj = {
title: 'Holiday',
author: 'Stanley Middleton',
age: 45
}
// INITIALIZATION
methodsObj = {
method1: methodImpl
}
app.mount('#app')
Now, let's revisit the same code but replace methods: {method1: methodImpl}
with methods: methodsObj
:
// 👇 HOISTED DECLARATIONS
var dataObj = undefined;
function dataFunction (){
return dataObj
}
var methodsObj = undefined;
function methodImpl (){
this.title = 'Infinite Jest'
}
// 👆 HOISTED DECLARATIONS
const app = Vue.createApp({
data: dataFunction,
methods: methodsObj // ❌ methodsObj was not defined earlier, hence method1 would be undefined in the app
})
// INITIALIZATION
dataObj = {
title: 'Holiday',
author: 'Stanley Middleton',
age: 45
}
// INITIALIZATION
methodsObj = {
method1: methodImpl
}
app.mount('#app')
To resolve the issue with methodsObj
, it is recommended to declare and initialize it before using it:
// declare and initialize vars here...
var dataObj = {
title: 'Holiday',
author: 'Stanley Middleton',
age: 45
}
function dataFunction (){
return dataObj
}
var methodsObj = {
method1: methodImpl
}
function methodImpl (){
this.title = 'Infinite Jest'
}
// now, use the declarations from above
const app = Vue.createApp({
data: dataFunction,
methods: methodsObj
})
app.mount('#app')
Here's a visualization to illustrate the hoisting process:
// 👇 HOISTED DECLARATIONS
var dataObj = undefined;
function dataFunction (){
return dataObj
}
var methodsObj = undefined;
function methodImpl (){
this.title = 'Infinite Jest'
}
// 👆 HOISTED DECLARATIONS
// INITIALIZATION
dataObj = {
title: 'Holiday',
author: 'Stanley Middleton',
age: 45
}
// INITIALIZATION
methodsObj = {
method1: methodImpl
}
const app = Vue.createApp({
data: dataFunction,
methods: methodsObj // ✅ methodsObj is declared and initialized previously
})
app.mount('#app')
Check out the demo here
An important enhancement brought by ES2015 was the introduction of const
and let
keywords to address common bugs associated with hoisting like the one observed above. Consider replacing var
with const
/let
to prevent such issues in your codebase, and utilize a linter that discourages the usage of var
.