为什么'this'指的是'window'而不是类实例

时间:2016-09-19 11:19:12

标签: javascript reference

我有一个包装函数,我获取全局对象( root = this ),然后启用严格模式并声明一些函数。

在这个包装函数中,我有一个类,我正确地调用它(使用 new 运算符)。问题是在我的原型方法中访问此类的实例,因为它使用 this 引用全局对象。

这是我正在编写的代码,我删除了代码的一些不可忽视的部分,以推动自己解决问题。

注意:exports.Timer是使用_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']()
        }
    }

})

1 个答案:

答案 0 :(得分:2)

当你这样做时:

(state ? timer.start : timer.stop)()

然后表达式 timer.start 返回一个函数,然后在没有基础对象的情况下调用该函数,因此调用未定义 this ,因此在函数中,它默认为全局对象。它相当于:

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)());