0

why this logs 1 and not 2 ? i am trying to pass this scope to initData function but no success. after running init i should trigger iniData but this should refer to the object itself not to a new scope

    let startFunction = function (){
        let initData = () => {
            this.x = 2
        }
        return {
            x:1,
            init:initData.bind(this)
        };
    };
    obj=startFunction()
    obj.init();
    console.log(obj.x); // should be 2


update:

    let startFunction = function (){
    let initData = function(){
        this.x = 2
    }
    return {
        x:1,
        init:initData
    };
};
    obj=startFunction()
    obj.init();
    console.log(obj.x); // should be 2

and why this works ? shouldn't the function create a new scope ?

1
  • x in the returned object has nothing to do with the this.x. Is there a reason you are avoid using a class? Commented Aug 24, 2022 at 19:02

2 Answers 2

1

There are two issues here. The first issue is that arrow functions are immutably bound to their execution context. Function.prototype.bind has no effect on an arrow function. The second issue here is what this refers to when you call startFunction. When you invoke a function freely, without a binding to a particular object, this refers to the object in which the function is invoked. So this refers to the global object in initData permanently.

So let's think about the value of obj and the global object's x value after each line.

After obj=startFunction:

// global x is undefined

// obj
{
  x: 1,
  init: initData // with the same binding to the global object
}

After obj.init(), initData sets the global object's x value to 2:

// global x is 2

// obj
{
  x: 1,
  init: initData // with the same binding to the global object
}
Sign up to request clarification or add additional context in comments.

Comments

1

Problem you are facing is the x in the object has nothing to do with the this.x that is being assigned in the init method. You need to set an object and in the init code adjust that object.

let startFunction = function() {

  const initData = () => {
    data.x = 2
  };
  
  var data = {
    x: 1,
    init: initData,
  };
  
  return data;

};

const obj = startFunction()
obj.init();
console.log(obj.x);

Better solution, use a proper class.

class MyClass {
 x = 1;
 init() {
   this.x = 2;
 }
}

const obj = new MyClass();
obj.init();
console.log(obj.x);


class MyClass2 {
 x = 1;
 constructor() {
     this.x = 2;
 }
}

const obj2 = new MyClass2();
console.log(obj2.x);

2 Comments

The .bind is unnecessary in this solution, and it has no effect on an arrow function.
let startFunction = function (){ let initData = function(){ this.x = 2 } return { x:1, init:initData }; }; obj=startFunction() obj.init(); console.log(obj.x); // should be 2

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.