Javascript Object / Function Question
I have an instance of a logging class "logger", this class has a function "log(txt)", which works.
Now I am declaring a different class "Runner" and I pass it the logger instance in the constructor. Everything works until line 5, but line 7 does not write to the log:
var Runner = function (logger) {
// constructor:
logger.log("this way it works");
this.logger = logger; //line 4
this.logger.l开发者_开发问答og("this also works"); //line 5
this.logf = this.logger.log; //create a shorthand for logging
this.logf("this is not written to log. why? i thought i can create a var for a function"); //line 7
};
var logger = new Logger(); //class not shown here
var runner = new Runner(logger);
var otherinstancce = new OtherClass(logger) //line 12
Can you explain what is my mistake?
When you assign the log
function to the logf
member of the current object it becomes a member function of this current object. When you call is, the this
object inside of the function will refer to it's new object, not to this.logger
anymore. Therefore the function will not find variables other functions it wants to call on the logger object.
To avoid this, you can write a simple function that forwards to the logger object:
this.log = function() { return this.logger.log(arguments); }
Or, using a closure:
var obj = this.logger;
this.log = function() { return obj.log(arguments); }
unlike some other languages, "this" in javascript is dynamic, that is, "this" is the context in which the function was called, not where is was defined.
function Foo() {
this.x = 1;
this.func = function() { alert(this.x) }
}
foo = new Foo
foo.func() // works
var copy = foo.func
copy() // nope, because func() lost its context
to create coupling between function and its context you have to "lock" the context in a closure. Most frameworks provide a sugar for this in form of bind() method, which, in simplified form, looks like this
Function.prototype.bind = function(o) {
var p = this;
return function() { p.apply(o) }
}
with locked context function assignment works as expected
bar = foo.func.bind(foo)
bar() // yes!
I think the issue might be this.logf is running within the scope of the runner object as opposed to the logger. If your logger.log function uses "this" at all, it will be using the runner instead of the logger.
精彩评论