-1

I have this code:

function myFunction() {

  console.log("Something")

  this.somethingElse = event => console.log("Something else")

}

When I evoke the function using myFunction() I get Something printed out in the console. But evoking myFunction.somethingElse() throws an error saying myFunction.somethingElse() is not a function.

What am I getting wrong?

3 Answers3

1

You can return this, then call the function using return value of function call, optionally using new keyword to prior to function invocation

function myFunction() {

  console.log("Something")

  this.somethingElse = event => console.log("Something else")
  return this
}

var fn = new myFunction();
fn.somethingElse();
guest271314
  • 1
  • 10
  • 82
  • 156
  • Don't return from a constructor. – Andrew Li Aug 13 '17 at 03:38
  • @AndrewLi Can you share reasons for not returning a value where `new` is used prior to function invocation? – guest271314 Aug 13 '17 at 03:40
  • 2
    JavaScript *already does this for you*, it returns the new instance. It's just redundant and isn't executed IIRC. – Andrew Li Aug 13 '17 at 03:43
  • 1
    Whenever you are creating an instance of a function using `new`, essentially you are creating a new object, and providing it's reference to the new vairable `fn`. So even if you dont return `this`, the variable `somethingElse` will be available in the `fn`. It would have been other case if you have called the `myFunction` directly without `new`. – Anurag Singh Bisht Aug 13 '17 at 03:45
  • @AndrewLi Will leave code unadjusted for context of relation to helpful comments. Another option would be to just return the function `function myFunction() { console.log("Something") var somethingElse = event => console.log("Something else") return somethingElse } var fn = myFunction(); fn()` – guest271314 Aug 13 '17 at 03:51
  • 1
    @AndrewLi it _is_ redundant, but it _is_ also executed. For instance, you could write a specialized constructor that memoizes instances with equivalent values by alternatively checking a `Map` and returning an instance declared with the same input value, e.g. `var cache = new Map(); function MyClass(input) { if (cache.has(input)) return cache.get(input); this.value = input; cache.set(input, this); }` – Patrick Roberts Aug 13 '17 at 04:12
1

In Javascript, this in a function, is the context in which the function is called. In other words, the object which is invoking the function.

In your case, when you do myFunction(), you are essentially calling window.myFunction(). So the this becomes window.

So your function will print the console - Something. It will add somethingElse in your window. So if you try to access myFunction().somethingElse is wrong, Because somethingElse is not part of your function.

But if you try to execute myFunction() and then somethingElse, it will print in the console - Something else.

function myFunction() {

  console.log("Something")

  this.somethingElse = event => console.log("Something else")

}

myFunction();

somethingElse()
Anurag Singh Bisht
  • 2,320
  • 2
  • 16
  • 24
  • *"In your case, when you do `myFunction()`, you are essentially calling `window.myFunction()`. So the `this` becomes `window`."* This is not correct. It may appear so for global functions, but since `this` also points to `window` in functions that are *not* global, thinking about it this way does more harm than good IMO. – Felix Kling Aug 13 '17 at 05:45
  • I was talking about the particular question. In this scenario, it is referring to the `window`. Isn't it ? – Anurag Singh Bisht Aug 13 '17 at 05:46
  • Maybe my comment wasn't clear. Yes, `this` refers to `window`, but **not** because the OP is "essentially calling `window.myFunction()`". That's the wrong way to think about it. The fact that `this` points `window` is simply a special case and cannot be explained with the function being invoked as a "method" of the `window` object. – Felix Kling Aug 13 '17 at 05:47
  • I was just making a point that in this case, when a function is declared it will get attached to `window`. So if we call without any object reference, `this` inside the function will be pointing to the `window`. If it was called with respect to an object, as in `obj.myFunction`, `this` will be referring to the `obj`. I agree it will not be the case always. But that's why I mentioned `in your case`. – Anurag Singh Bisht Aug 13 '17 at 05:55
  • *"when a function is declared it will get attached to `window`"* That's only the case for global functions. Consider `function foo() { function bar() { console.log(this); }; bar(); }; foo();`. `bar` is not global and still `this` inside of it points to `window`. Hence why I am saying that this explanation is misleading. It doesn't explain what's actually happening. – Felix Kling Aug 13 '17 at 06:07
  • In your example also, you can see that first `foo` is called in context of `window`. So `this` is referring to `window` inside `foo`. Now when you call `bar()` inside `foo`, still the context is `window`. Ans hence `this` inside `bar` will be `window`. I am agreeing with you that it will not be the case always. But I have tried to explain it as clearly as possible. – Anurag Singh Bisht Aug 13 '17 at 06:12
  • What `this` refers to in `foo` has no impact on `bar`! Your understanding is not correct. Consider this example then: `var obj = {foo() { function bar() { console.log(this); bar(); }}; obj.foo();`. `this` inside `foo` is `obj`. `this` inside `bar` is `window`. – Felix Kling Aug 13 '17 at 06:14
  • @FelixKling There is a missing closing `}` at your last example. Also `bar()` is within `bar` function `var obj = { foo() { function bar() { console.log(this); } bar() } }; obj.foo()` – guest271314 Aug 13 '17 at 06:17
  • 1
    @guest271314: Too late to edit ;) Hope the point is clear though. – Felix Kling Aug 13 '17 at 06:21
  • Yup I agree with you. My understanding is that the `this` inside a function is the context in which it is called. When the `context` is not provided it refers to the `global scope`. In case `myFunction()` was called directly there was no scope provided, hence it was referring to `window` as `this` inside it. Now when you have called `foo` with respect to `obj`, `this` inside `foo` is referring to `obj`. Now when `bar` is being called, there is no `context` and it's referring to `global` scope. – Anurag Singh Bisht Aug 13 '17 at 06:22
0

I invoked this inner function by returning it as the value of an object's property (i.e. a 'method' in JavaScript) like so:

function myFunction() {

  console.log("Something")

  return {
    somethingElse: function() {
      console.log("Something else");
    }
  }
}

myFunction().somethingElse()
nate_js
  • 26
  • 1
  • 1
  • 4