-1

I am new in js. I am trying to understand how to use "this" correctly. I want to create an object with a behaviour. When the object created, the person is given a name and length of his step.

My question is how I can save the quantity of steps inside the function? how to do it correctly without losing context, because my this always looks to the global object.

Roy Fied
  • 29
  • 2
  • 1
    How are you calling these methods? – VLAZ Apr 22 '21 at 18:55
  • You need "instances" of the object. You should be creating a function, rather than an object literal. Then, you can make "instances" of that object (with the `new` keyword) and `this` will bind to that particular instance. – Scott Marcus Apr 22 '21 at 18:55
  • Relevant: [How to access the correct `this` inside a callback?](https://stackoverflow.com/q/20279484) and [How does the “this” keyword work?](https://stackoverflow.com/q/3127429) – VLAZ Apr 22 '21 at 18:56
  • 1
    @ScottMarcus there is no need for classes or instances here (imo using "classes" in JS is an antipattern, despite ES6 giving specific syntactic support for it, although I accept that's simply an opinion which many would dispute). `person` is already an object, that would be considered an "instance" in most other languages - simply calling `person.summary()` and `person.stepIncrease()` etc should work fine, if this isn't working for the OP they should share their code. – Robin Zigmond Apr 22 '21 at 19:00
  • @RobinZigmond I did not recommend classes (and I personally agree with you on that topic). However, I interpreted the question (being about `this`) as being able to keep the data from multiple uses of `Person` separate from one another. You won't get that behavior with just calling a method on an object literal because it represents a single instance. You need to be able to make separate instances of a `Person` object that are distinct. – Scott Marcus Apr 22 '21 at 19:03
  • @ScottMarcus ok, but you did explicitly talk about "instances" and the `new` operator - `new` is only used either with ES6 "classes" or their pre-ES6 "fake" classes using functions. I'm happy with "factory functions" which return objects, which (imo) avoids the conclusion of JS "classes" - but those do not require the use of the `new` operator. And in any case it's not clear from the OP's question whether they need such a factory to make multiple independent "instances" or if they in fact just want to call methods on the single `person` object. – Robin Zigmond Apr 22 '21 at 19:06
  • @RobinZigmond Using a `function` to create instances isn't "fake classes", nor are they "factory functions" (despite acting like them). In JS, a function used in conjunction with `new` is a first-class citizen, known as a "Constructor Function" and for `function` to be utilized as a "Constructor Function", the use of `new` is in fact required. If you don't use `new`, then you are using either an object or a method(depending on where the function is defined). (cont.) – Scott Marcus Apr 22 '21 at 19:14
  • @RobinZigmond ... This syntax and pattern is how "prototypical inheritance" and object instantiation is actually leveraged within the language. Again, the question (being about `this`) strongly implies that multiple instances need to be kept separate from each other and (if you don't use classes), then constructor functions are how that is done. – Scott Marcus Apr 22 '21 at 19:14

3 Answers3

2

You can either use a function (not an arrow function) or a class. I have added a code sample of how you can create objects using function

function Person(name) {
    this.name = name;
    this.step =1;
    this.stepIncrease = function() {
        this.step++;
    }
    this.summary = function () {
    return this.step;
    }
}
const person = new Person("john");
vanshaj
  • 374
  • 2
  • 11
2

You need to create a function that will return the person's object. Then, to create a new object, you can use the new keyword and call the function. This will create an object on the fly and assign the this pointer to the object itself.

Things to note about the this:

  • If a function is called with .call(), .apply() or .bind(), this will be the object that is passed inside the call/apply/bind.
  • If a function is called on an object e.g. obj.foo(), this will be the object it was called on.
  • If a function is called on its own, foo(), this will be either undefined (strict mode) or the global object (non-strict mode)

function Person(name, step=1) {
    return {
        name, 
        step,
        stepIncrease: function() {
            this.step++;
            return this;
        },
        summary: function() {
            console.log(this.step);
        }
    }

}

const john = new Person('John');
john.stepIncrease();
console.log(john);
Krantisinh
  • 1,357
  • 8
  • 13
  • 1
    There is no need for `new` here `Person("John")` will work identically to `new Person("John")` since the constructor function overrides the return value and doesn't use the `this` that `new` provides. – VLAZ Apr 22 '21 at 19:07
  • yes, that's correct. – Krantisinh Apr 22 '21 at 19:13
0

with Class

class Person {
  name = "";
  step = 1;
  
  stepIncrease() {
    this.step++;
  }
  
  summary() {
    console.log(this.step);
  }
}

const person1 = new Person();
for(let i = 0; i < 5; i++) {
  person1.stepIncrease();
}
person1.summary();
Josh
  • 139
  • 9