angularjs服务无法访问属性

时间:2015-03-20 22:20:13

标签: angularjs

我有一个这样的课程设置:

.factory('DesignerService', function () {
    var kit = {
        clubName: 'Moss side archery club',
        teamName: 'The flying arrows',

        selectedColours: ['082140', '841c3d'],
        selectedGarments: ['hoody'],
        selectedDesign: "Angelus",

        total: '00.00',
        templates: []
    };

    var getTemplates = function () {
        var templates = [];

        console.log(kit);

        for (var i = 0; i < kit.selectedGarments.length; i++) {
            var garment = kit.selectedGarments[i];

            kit.templates.push('/assets/garments/' + garment + '.svg');
        }

        return kit;
    };

    var getColours = function () {
        return ['000000', 'FFFFFF', '00adef', 'ed008c', 'fef200', '2e3192', '00a652', 'ed1b24', 'c7c8ca', 'f14e23', '6c9d30', 'c0d731', 'f5a3c7', '816ab0', '082140', '1e4f2f', '5bcaf5', 'f04e3f', 'f68b1f', 'cdbe01', 'ee4d9b', '007193', '5f1e08', '841c3d'];
    };

    var getGarments = function () {
        return ['Shirt', 'Track top', 'Skirt', 'Hoody', 'Socks', 'Shorts', 'Track pants', 'Polo shirt', 'Beanie hat', 'T - shirt'];
    };

    var getDesigns = function () {
        return ['Angelus', 'Claudius', 'Equitius', 'Octavius', 'Valerius']
    }

    var addToArray = function (array, item) {
        array.push(item);
    };

    var removeFromArray = function (array, item) {
        var index = array.indexOf(item);

        if (index > -1) {
            array.splice(index, 1);
        }
    };

    var modifyArray = function (array, value) {
        var i = array.indexOf(value);

        if (i > -1) {
            removeFromArray(array, value);
        } else {
            addToArray(array, value);
        }
    }

    var setColour = function (colour) {
        return modifyArray(kit.selectedColours, colour);

        return kit;
    };

    var setGarment = function (garment) {
        console.log(kit);

        modifyArray(kit.selectedGarments, garment);

        var kit = getTemplates();

        console.log(kit);

        return kit;
    };

    var setDesign = function (design) {
        kit.selectedDesign = design;

        return kit;
    };

    return {
        kit: kit,

        getTemplates: getTemplates,
        getColours: getColours,
        getGarments: getGarments,
        getDesigns: getDesigns,

        setColour: setColour,
        setGarment: setGarment,
        setDesign: setDesign
    };
})

如果我调用函数 setGarment ,则第一个console.log(kit)会在 kit.selectedGarments 中返回undefined以及 modifyArray 错误。 但如果我注释掉这一行:

  
    

// modifyArray(kit.selectedGarments,服装);

  

然后 getTemplates 实际记录工具包对象并返回更新后的对象。

有人可以解释原因吗?

更新1

好的,现在我理解了这些悬挂的东西,我重新设计了我的服务,看起来像这样:

.factory('DesignerService', function () {
    var self = this;

    var addToArray = function (array, item) {
        array.push(item);
    };

    var removeFromArray = function (array, item) {
        var index = array.indexOf(item);

        if (index > -1) {
            array.splice(index, 1);
        }
    };

    var modifyArray = function (array, value) {
        var i = array.indexOf(value);

        if (i > -1) {
            removeFromArray(array, value);
        } else {
            addToArray(array, value);
        }
    }

    self.kit = {
        clubName: 'Moss side archery club',
        teamName: 'The flying arrows',

        selectedColours: ['082140', '841c3d'],
        selectedGarments: ['hoody'],
        selectedDesign: "Angelus",

        total: '00.00',
        templates: []
    };

    self.getTemplates = function () {
        var templates = [];

        for (var i = 0; i < self.kit.selectedGarments.length; i++) {
            var garment = self.kit.selectedGarments[i];

            self.kit.templates.push('/assets/garments/' + garment + '.svg');
        }

        return self.kit;
    };

    self.getColours = function () {
        return ['000000', 'FFFFFF', '00adef', 'ed008c', 'fef200', '2e3192', '00a652', 'ed1b24', 'c7c8ca', 'f14e23', '6c9d30', 'c0d731', 'f5a3c7', '816ab0', '082140', '1e4f2f', '5bcaf5', 'f04e3f', 'f68b1f', 'cdbe01', 'ee4d9b', '007193', '5f1e08', '841c3d'];
    };

    self.getGarments = function () {
        return ['Shirt', 'Track top', 'Skirt', 'Hoody', 'Socks', 'Shorts', 'Track pants', 'Polo shirt', 'Beanie hat', 'T - shirt'];
    };

    self.getDesigns = function () {
        return ['Angelus', 'Claudius', 'Equitius', 'Octavius', 'Valerius']
    }

    self.setColour = function (colour) {
        return modifyArray(self.kit.selectedColours, colour);

        return self.kit;
    };

    self.setGarment = function (garment) {
        modifyArray(self.kit.selectedGarments, garment);

        self.getTemplates();

        return self.kit;
    };

    self.setDesign = function (design) {
        self.kit.selectedDesign = design;

        return self.kit;
    };

    return self;
})

这是正确的方法吗?

3 个答案:

答案 0 :(得分:4)

这看起来像是一个Javascript variable hoisting问题。 Javascript解释器通过代码进行两次传递。第一遍,它查找变量声明,第二遍传递它执行代码。这基本上是对您的代码执行以下操作:

var kit = getTemplates()

变为:

var kit;
kit = getTemplates();

此时,Javascript解释器将首次通过,寻找变量声明(var kit)。下一遍将实际执行代码(kit = getTemplates())。基本上,您的代码变为:

var kit;

console.log(kit); // kit is undefined

modifyArray(kit.selectedGarments, garment); // kit is still undefined

kit = getTemplates(); // kit is no longer undefined

console.log(kit); // kit will log out properly here

return kit;

希望这是有道理的。简单的解决方案是将您的范围kit变量重命名为其他内容(可能是scoped_kit)。通常,最好不要将变量名称从一个范围隐藏到另一个范围。

希望这有帮助!

答案 1 :(得分:1)

您遇到了悬挂问题。

在javascript中,您可以在声明之前初始化并使用变量。

x = "hello";
y = "world";
var x, y;

document.getElementById("message").innerHTML = x + " " + y;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="message"></div>

声明已提升,但初始化不是。

var x = "hello";

document.getElementById("message").innerHTML = x + " " + y;

var y = "world";
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="message"></div>

功能表现略有不同。函数声明可以在声明它们之前在代码中使用,这是因为它们在任何代码运行之前被加载,并被提升。

alert(works());
function works() { ... };

函数表达式不同。它们在代码中到达之前不会加载。

alert(doesntWork());  
var doesntWork = function() { ... };

// Function declarations have their bodies hoisted.

document.getElementById("message1").innerHTML = y();

function x() { return "hello"; };
function y() { return x() + " world"; }

// Function expressions only load when the code is reached, they need to be declared before being used. 

// document.getElementById("message2").innerHTML = b(); <-- This would cause an error.

var a = function() { return "hello"; },
    b = function() { return a() + " world"; };

document.getElementById("message2").innerHTML = b();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="message1"></div>
<div id="message2"></div>

答案 2 :(得分:1)

由于您从OOP方面接近Angular工厂并提及公共“班级”成员,因此将其称为this.kit而不是kit是一种很好的做法(他们不会如果服务的kit属性已更改,则相等。它还使代码明确且可读。

本地var kit的问题是经典的JS吊装问题,正如比尔·伯格奎斯特的答案所解释的那样。