Reputation: 417
Let's say I have this code
(function() {
function Foo(arg) {
this.name = arg;
}
Foo.prototype = {
bar: {
baz: function() {
alert(this.name); // Undefined...
}
}
}
var foo = function(arg) {
return new Foo(arg);
};
window.foo = foo;
return foo;
}());
foo("Anything").bar.baz();
How can I make "this" in my function "baz" refers to the object Foo without using bind or apply when I call it from outside ?
Upvotes: 1
Views: 85
Reputation: 1074168
FWIW, I would strongly recommend not building nested structures like that, or at least not on the prototype, because the bar
object is shared amongst all of the instances, which opens the door to a lot of cross-talk-style bugs. Instead, I'd create bar
within the constructor.
How can I make "this" in my function "baz" refers to the object Foo without using bind or apply when I call it from outside ?
You may have bind
and apply
/call
slightly confused. You wouldn't use bind
when calling the function, but when creating it. Unless you use bind
(or something equivalent to it), you can't do what you've said you want, because absent bind
(or similar), this
is set by how the function is called, and so this.bar.baz()
will make this
be this.bar
within the call.
Here's how you'd build bar
within the constructor, and use bind
to make baz
use the correct this
:
function Foo(arg) {
this.name = arg;
this.bar = {
baz: function() {
alert(this.name);
}.bind(this) // <== Note
};
}
Example:
function Foo(arg) {
this.name = arg;
this.bar = {
baz: function() {
snippet.log(this.name);
}.bind(this) // <== Note
};
}
var f1 = new Foo("f1");
var f2 = new Foo("f2");
f1.bar.baz(); // "f1"
f2.bar.baz(); // "f2"
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
More about cross-talk: The naive thing to do is to just add one line to your Foo
constructor, and keep bar
on the prototype:
this.bar.baz = this.bar.baz.bind(this);
That would be a very bad idea, because you'd get cross-talk between instances:
function Foo(arg) {
this.name = arg;
this.bar.baz = this.bar.baz.bind(this); // DON'T DO THIS
}
Foo.prototype = {
bar: {
baz: function() {
snippet.log(this.name);
}
}
};
var f1 = new Foo("f1");
var f2 = new Foo("f2");
f2.bar.baz(); // "f1" -- cross talk! Should be f2
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Upvotes: 2
Reputation: 142
Use bind at declaration time to properly scope this, e.g.
function foo() {}.bind(this);
Upvotes: 0