如何保持这个'在一个javascript闭包中的类中

时间:2016-02-19 20:36:06

标签: javascript closures

我已阅读this answerIIFE,但我似乎无法找到解决问题的正确方法。

我这里有一个简单的课程:

define(['jquery'], function($) {
    // Need 'self' because someCallback() is being called with .call() and 'this' changes
    var self;

    function Foo(number) {
        self = this;
        this.someNumber = number;
    }

    Foo.prototype = {
        someCallback: function () {
            //Use self because 'this' changes to a DOM element
            var num = self.someNumber;

            //Do something with the num
            return num * 2;
        }
    };

    return Foo;
});

someCallBack()由jQuery插件使用.call()调用。因此,上下文发生了变化,因此使用了self变量。

然而,这是错误的,因为:

define(['foo'], function(Foo) {
    describe('context question', function () {
        var foo1 = new Foo(1);
        var foo2 = new Foo(2);

        it('"this" should work', function () {
            var call1 = foo1.someCallback.call(this); // 4
            var call2 = foo2.someCallback.call(this); // 4

            expect(call2).toBe(4); // Only works because it is 'new' last
            expect(call1).toBe(2); // Fails because 'self' is taken from foo2
        });
    });
});

我应该如何包装self变量以使此代码有效?

2 个答案:

答案 0 :(得分:1)

您可以使用frame-ancestors并将其声明为“全局”变量(模块的本地变量):

define(['jquery'], function($) {
    var someNumber;

    function Foo(number) {
        someNumber = number;
    }

    Foo.prototype = {
        someCallback: function () {
            return someNumber * 2;
        }
    };

    return Foo;
});

答案 1 :(得分:1)

调用存储其自身值的对象方法的两种方法包括

  1. 将方法定义为嵌套函数,该函数在闭包中引用其值,该闭包在变量中存储this值。定义的函数可以是匿名的,也可以使用名称声明,但每次创建类实例时都必须进行评估,以便创建一个新的Function对象,在函数范围内捕获self的不同值。

  2. 使用静态定义的函数对象并使用bind绑定其值。 Bind每次调用它时都会创建一个新的包装函数对象。

  3. 第一种方法看起来像(没有Jquery或Jasmine):

    function Foo(number)
    {   var self = this;
        this.num = number;
        this.someCallback = function()  // method with new Foo object stored as self in function scope 
        {   // something with num:
            return self.num * 2;
        }
    }
    

    ,第二种方法看起来像

    function Foo(number)
    {   this.num = number
        this.someCallback = this.someCallback.bind(this); // bind prototypical method as local method.
    }
    
    Foo.prototype = {
        someCallback: function () {
            // this value is bound by constructor;
            //Do something with the num
            return this.num * 2;
        }
    };