0

While I was trying to grasp reactivity fundamentals and its syntax I've encountered following problem. Consider this snippet:

const app = Vue.createApp({
   data: dataFunction,
   methods: {method1:  methodImpl}
})
var dataObj = {
    title: 'Holiday',
    author: 'Stanley Middleton',
    age: 45
}
function dataFunction (){
    return dataObj
}
var methodsObj = {
    method1:  methodImpl
    
}
function methodImpl (){
    this.title = 'Infinite Jest'
}
app.mount('#app')

and html behind it:

<div id="app">
        [...]
        <div @click="method1">change book title</div>
</div>

This code works and I was able to extract data into separate function and object but how can I do it with method ? This methods: methodsObj doesn't work - obviously. I want to be able to use my methodsObj in createApp initialization. Is it possible? I know it is purely academic but such exercises help me understand syntax and object relations.

1
  • There's no specific syntax for Vue here. These are the basics of JS. It is methods: methodsObj. Also it doesn't make sense to define dataObj outside dataFunction, the reason why data is a function is that this allows to return a new object each time it's called and not share it between component instances Commented May 13, 2022 at 0:34

1 Answer 1

2

In JavaScript, vars are hoisted, but their initializations are not. functions and their definitions are also hoisted. Your code relies on hoisting, which can be problematic.

Here's a visualization of the hoisting in your original working 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 declared above
})
// INITIALIZATION
dataObj = {
    title: 'Holiday',
    author: 'Stanley Middleton',
    age: 45
}
// INITIALIZATION
methodsObj = {
    method1:  methodImpl
}

app.mount('#app')

Now consider that 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 undefined above, so method1 would be undefined in the app
})
// INITIALIZATION
dataObj = {
    title: 'Holiday',
    author: 'Stanley Middleton',
    age: 45
}
// INITIALIZATION
methodsObj = {
    method1:  methodImpl
}

app.mount('#app')

The issue with methodsObj in the example above can be fixed by declaring and initializing it before usage (which is generally a best practice):

// 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')

And here's the visualization of the hoisting above:

// 👇 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 declared and initialized above
})

app.mount('#app')

demo

One of the motivations of const and let (introduced in ES2015) was to avoid common bugs from var hoisting, such as you observed above. If you had used const/let instead of var in your original code, the compiler would've thrown an error, which might've signaled to you then that the declaration should be moved above the usage. Consider using a linter that discourages the use of var.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.