我在创建一个全局变量吗?

时间:2016-02-08 22:18:41

标签: javascript angularjs jasmine

我正在创建一个使用Jasmine测试Angular过滤器的函数。规格由Karma运行。我们的想法是传递一个模块和过滤器名称,并在其上执行一系列测试。该数组的每个元素都有描述,输入值和预期结果。但它也可以包含testSteps函数,用于测试,这些测试不像传递输入值那样简单并且期望精确值。我正在创建的函数是为了创建相应的Jasmine描述并阻止测试,它在一个定义如下的全局变量中:

#include <stdio.h>

void capitalize(char *str)
{
    char *p = str;
    while(*p++) {
        if (*p >= 97 && *p <= 122) {
            *p -= 32;
        }
    }
}

void strCopy(char *str2, char *str1)
{
    while (*str2) {
        *str1 = *str2;
        str2++;
        str1++;
    }
    *str1 = '\0';
}

int main(int argc, char **argv)
{
    char string1[100] = "This is a really long string!";
    char string2[100];
    strCopy(string1, string2);
    capitalize(string2);
    printf("The original string is \"%s\"\n", string1);
    printf("The capitalized string is \"%s\"\n", string2);
}

我的测试代码是:

var $uite = {
    testFilter : function(filterName, moduleName, tests) {
        this.filterObject = null;
        this.isDefined = function(vble) {
            return typeof (vble) != 'undefined';
        }
        describe('FILTER: ' + filterName, function() {

            beforeEach(module(moduleName));
            beforeEach(inject(function($filter) {
                filterObject = $filter(filterName);
            }));

            for (var i = 0; i < tests.length; i++) {
                var test = tests[i];
                it(test.it, function() {
                    if (typeof (test.forInputValue) != 'undefined') {
                        var result = filterObject(test.forInputValue);
                        expect(result).toEqual(test.resultShouldBe);
                    } else if (typeof (test.testSteps) != 'undefined') {
                        test.testSteps();
                    }
                });
            }
        });
    }
}

它工作得很好,但仅仅是为了好奇,因为我避免创建不必要的全局变量,我在它们之后编写了以下测试:

$uite.testFilter('nameFilter', 'app', [ {
    it : 'gets male gender from a name ending in O',
    forInputValue : 'Pedro',
    resultShouldBe : 'el tal Pedro'
}, {
    it : 'gets female gender from a name ending in A',
    forInputValue : 'Carolina',
    resultShouldBe : 'la tal Carolina'
}, {
    it : 'transforms Lina into la tal Lina',
    testSteps : function() {
        var result = filterObject('Lina');
        expect(result).toEqual('la tal Lina');
    }
} ]);

由于filterObject的类型是函数,因此失败。如果我的filterObject是在$ uite对象中定义的并且不是(是吗?)隐式声明的,那么为什么它可以从另一个describe / it块集中访问?

1 个答案:

答案 0 :(得分:1)

您的问题:我是否在创建全局变量?

TL; DR

完整答案

这是全球性的。你在这里做全球化:

filterObject = $filter(filterName);

如果你之前没有放置var,并且你没有使用严格模式(例如use strict;),那么它将是全局的。

如果您想要引用this,则需要在任何地方使用this

beforeEach(inject.call(this, function($filter) {
    this.filterObject = $filter(filterName);
}.bind(this)));

或类似的东西。或者,您可以声明var _this = this

beforeEach(inject(function($filter) {
    _this.filterObject = $filter(filterName);
}));

在整个代码中的其他任何位置,您都需要将其称为this.filterObject

仅供参考,有关strict mode (article on MDN)的说明(我总是建议使用它,因为它会捕获意外的全局变量),请参阅“将错误转换为错误”部分:

  

首先,严格模式使得无法意外地创建全局变量。

其他参考资料:

  1. Function.prototype.bind on MDN
  2. Function.prototype.call on MDN
  3. P.S。看起来你是来自Java背景。使用对象时,定义this.<whatever>然后尝试将其简称为<whatever>将无法在JavaScript中使用,就像您期望它在Java中一样。

    修改

    要在第三次测试中访问filterObject,请执行以下操作:

    // ... in $suite
    } else if (typeof (test.testSteps) != 'undefined') {
        // make this.filterObject available as a parameter
        test.testSteps(this.filterObject);
    }
    
    // then in your test definition...
    
    }, {
        it : 'transforms Lina into la tal Lina',
        testSteps : function(filterObject) {  // this line is important
            var result = filterObject('Lina');
            expect(result).toEqual('la tal Lina');
        }
    } ]);