0
function Person(first, last) {
    return {
        first: first,
        last: last,
        fullName: function() {
            return this.first + ' ' + this.last;
        },
        fullNameReversed: function() {
            return this.last + ', ' + this.first;
        }
    };
}
p = Person("James", "Bond");
var fullName = p.fullName;
fullName();

I was expecting Output = 'James Bond' but get 'undefined undefined'

  • No need for `this`. `fullName: () => { return first + ' ' + last; }` – Ruan Mendes Mar 27 '22 at 13:21
  • Can you explain the reason please @Jaun Mendes – Vishal Gupta Mar 27 '22 at 13:28
  • @VishalGupta because the name is Bond, James Bond (if you know what I mean) – Muhammad Usman Mar 27 '22 at 13:29
  • 1
    When you assign `p.fullname` to a variable it loses the `this` context. `this` is set on method invocation, and is set to the object upon which you call the method. Eg. `p.fullname()` would set `this` in `fullname` to `p`. When you store the method in a variable and then call it by itself `fullname()`, `this` will be set to `undefined` when in strict mode, or to the global object `window` when not in strict mode. If you want to use `fullname` as a function you could define it as such: `var fullname = () => p.fullname`. – 3limin4t0r Mar 27 '22 at 13:36
  • 1
    Note that the comment of Juan does also solve the issue, but if you are re-assigning the `first` or `last` properties of `p`, the `fullname` method won't produce a new output. eg. `p = Person("James", "Bond")`, then `p.first = "John"`, then `p.fullname() //=> "James Bond"` This is because `fullName: () => first + ' ' + last` uses the constructor params, not the current object properties. – 3limin4t0r Mar 27 '22 at 13:43
  • 1
    My first comment has a typo `var fullname = () => p.fullname` is missing one set of parentheses and should be `var fullname = () => p.fullname()`. – 3limin4t0r Mar 27 '22 at 13:50
  • function Person(first, last, mid) { middle = mid; return { first: first, last: last, fullName: function() { return this.first + ' ' + this.last + ' ' + this.middle; }, fullNameReversed: function() { return this.last + ', ' + this.first; } }; } p = Person("James", "Bond", "Mega"); var fullName = p.fullName; fullName(); But in this case middle returns correctly. Reason? – Vishal Gupta Mar 27 '22 at 13:53
  • 1
    `middle` is an implicit global. Therefore when `this = window`, you are accessing `window.middle`. – VLAZ Mar 27 '22 at 13:56
  • 1
    @VishalGupta Because `middle = mid`—without `let`, `const` or `var`—will set `window.middle = mid`. So when you call `fullname()` and you are not in strict mode, `window` is passed as `this`. Therefore `this.middle` will correctly access the value. Note that you run into issues when you would create multiple people, because they all share the same global `window.middle`. `p1 = Person("James", "Bond", "Mega")`, `p2 = Person("John", "Doe", "Peta")`, `const fullname = p1.fullname`, `fullname() //=> "undefined Peta undefined"` – 3limin4t0r Mar 27 '22 at 14:01
  • Thanks guys. I think I understood. So basically p.fullName assigns a function and not the object p and middle is a global variable and thus is accessed via window. Let me know if this is wrong. – Vishal Gupta Mar 27 '22 at 14:12
  • That is correct. – VLAZ Mar 27 '22 at 14:13
  • 1
    Correct, only at the moment of method invocation (when you use parentheses to call the method) is `this` assigned. – 3limin4t0r Mar 27 '22 at 14:13
  • Vishal, because you are not depending on `this`, you are just using the closure variables. It's a workaround for the `this` problem. – Ruan Mendes Mar 28 '22 at 13:44

0 Answers0