Reputation:
I've a wrapper function where I get the global object (root = this
), then I enable strict mode and declare some functions.
Inside this wrapper function I've a class and I call it correctly (using new
operator). The problem is to access a instance of this class inside my prototype methods, because it refers to the global object, using this
.
This is the code I'm writting, I removed some irrevelant parts of the code to push itself to the question.
Note: exports.Timer
is the class that makes use of _timer
.
(function(root, name, factory) {
'use strict'
factory(typeof root['exports'] === 'object' ? module.exports : root[name] = {})
})(this, 'timerEx', function(exports) {
var root = this
'use strict'
/* my class */
function _timer(id, options) {
this.anim = options.anim
this.delay = options.delay
this.exec = typeof (this.fnc = options.callback) === 'function'
this.id = id
}
_timer.prototype = {
'start': function() {
// here's the problem.
// this is equal to 'window'
console.log(this instanceof _timer) // false
this.state = true
if (this.isAnim = (this.anim && typeof requestAnimFrame === 'function')) {
this._then = receiveTime()
animRun(this)
} else timeoutRun(this)
},
'stop': function() {
if (this.state)
(this.isAnim ? cancelAnimFrame : clearTimeout)(this.xId)
this.isAnim = null
this.state = false
}
}
var timers = []
function getReservedTimerId() {
var len = timers.length - 1
if (len <= 0) return 0;
for (var i = 0, reserved; i <= len; ++i) {
if (i === len)
reserved = i + 1
else if ((timers[i].id + 1) < timers[i + 1].id) {
reserved = timers[i].id + 1
break
}
}
return reserved
}
function getTimerById(id) {
var timer
for (var i = 0, len = timers.length; i < len; ++i) {
if (timers[i].id === id) {
timer = timers[i]
break
}
}
return timer
}
exports.Timer = function(options) {
typeof options !== 'object' && (options = {})
for (var i in def_options)
typeof options[i] !== typeof def_options[i] && (options[i] = def_options[i])
var id = getReservedTimerId()
timers.push(new _timer(id, options))
this.__id__ = id
}
exports.Timer.fn = exports.Timer.prototype = {
'delay': function(rate) {
getTimerById(this.__id__).delay = rate
},
'toggle': function(state) {
var timer = getTimerById(this.__id__)
timer[(typeof state === 'boolean' ? state : timer.state) ? 'stop' : 'start']()
}
}
})
Upvotes: 0
Views: 95
Reputation: 147363
When you do:
(state ? timer.start : timer.stop)()
then the expression timer.start returns a function, which is then called without a base object so its this is undefined by the call, so in the function, it defaults to the global object. It's equivalent to:
var a = timer.start;
a();
function Foo(){};
Foo.prototype.start = function(){
return this instanceof Foo;
}
var a = new Foo();
console.log('Normal call: ' + a.start());
console.log('Conditional call: ' + (true? a.start : null)());
Upvotes: 1