Goldfish
Goldfish

Reputation: 73

JS Call Stack with context

All,

I have a bit of code that is essentially,

function b(){
    console.log(this);
}

function a(){
    console.log(this);
    b();
}

Window.call(context, a);

The output looks like:

Object(context)
Window

It looks like the nonstandard context is only preserved when calling call, all subroutines where a context is not specified are called with the original context. Is there any way to invoke a function with context, having its entire execution stack occupy that same context?

Thanks,

Upvotes: 0

Views: 127

Answers (2)

jfriend00
jfriend00

Reputation: 707766

There's a simple rule in Javascript. Every function call in Javascript sets a new value for this. If you aren't making a method call such as obj.method() or using .call() or .apply(), then this is set back to the Global object or to undefined in strict mode.

So, if you want to specifically control the value of this in either of your function calls, then you will need to use .call() or .apply() or perhaps even .bind(). There is no magic mode you can put Javascript in that will "preserve" this when you call other functions. It just doesn't work that way.

Architecturally, if you really want a specific value of this for several functions, then perhaps they should be methods on a common object because calling obj.method() will automatically set this to obj or you can use .call() or .apply() to manually specify what you want the this value to be for any function call.

In your code example, you could change:

function a(){
    console.log(this);
    b();
}

to this:

function a(){
    console.log(this);
    b.call(this);
}

And, b() would get executed with the same value of this as a().

Upvotes: 1

Pointy
Pointy

Reputation: 413826

You have to use .call() or .apply():

function a(){
    console.log(this);
    b.call(this);
}

You cannot flip the runtime into a mode wherein it implicitly does that, so the direct answer to your question is "no".

If you have a bunch of functions and want to create versions that always have some particular value for this, you can use .bind():

function b(){
    console.log(this);
}

function a(){
    console.log(this);
    b();
}

a = a.bind(context), b = b.bind(context);
a(); // logs context from both functions

That'd be a pretty unusual thing to do but it would work. You'd be out of luck if you wanted to use the functions with a different object.

Upvotes: 3

Related Questions