简体   繁体   English

将变量或属性值传递给JavaScript对象中的方法将返回“未定义”

[英]Passing a variable or property value to a method in a JavaScript object returns “undefined”

I'm trying to build an xml file from 2 JSON objects through 2 cascading loops. 我正在尝试通过2个级联循环从2个JSON对象构建xml文件。 In the second loop, I can't find how to pass a value from the previous loop: 在第二个循环中,我找不到如何从上一个循环传递值:

In the example below, I would like to pass the "docnumber" value to my second loop (through GroupsACLJSON) in order to build the "acl" node from the second JSON object, but using "this.docnumber" from the parent object property returns "undefined", thus leading to an empty "acl" node. 在下面的示例中,我想将“ docnumber”值传递给第二个循环(通过GroupsACLJSON),以便从第二个JSON对象构建“ acl”节点,但要使用父对象属性中的“ this.docnumber”返回“未定义”,从而导致一个空的“ acl”节点。

var documentsJSON = [{
    "folder": "Enterprise1",
    "extension": "DOCX",
    "docnumber": "3912271",
    "version": "1"
  },
  {
    "folder": "Enterprise2",
    "extension": "MSG",
    "docnumber": "3912298",
    "version": "1"
  },
  {
    "folder": "Enterprise3",
    "extension": "DOCX",
    "docnumber": "3912692",
    "version": "1"
  }
]

var GroupsACLJSON = [{
    "docNumber": "3912271",
    "groupName": "group1"
  },
  {
    "docNumber": "3912271",
    "groupName": "group2"
  },
  {
    "docNumber": "3912298",
    "groupName": "group3"
  },
  {
    "docNumber": "3912298",
    "groupName": "group4"
  }
]

// importing and declaring xmlbuilder variable: 
var builder = require('xmlbuilder');
var xmlObjectImporter = builder.create('import', {
  version: '1.0',
  encoding: 'UTF-8',
  standalone: true
}, {
  headless: false,
  stringify: {}
});

var nodeArray = [];
var xmlObjectElement = {
  node: function() {
    for (var i = 0; i < documentsJSON.length; i++) {
      // populate the nodeObject for each row in documentsJSON and add it to the nodeArray:
      var nodeObject = {
        location: documentsJSON[i].folder,
        category: {
          attribute: [{
            '#text': documentsJSON[i].docnumber,
            '@name': "Document Number"
          }],
          '@name': "ACME",
        },
        docnumber: documentsJSON[i].docnumber,
        // loop through GroupsACLJSON to find if we have specific ACL groups for this document:
        acl: function() {
          var documentNumber = this.docnumber
          console.log(this.docnumber);
          var acl = [];
          var aclObject = {};
          for (var j = 0; j < GroupsACLJSON.length; j++) {
            if (GroupsACLJSON[j].docNumber == documentNumber) {
              aclObject = {
                '@group': GroupsACLJSON[j].groupName,
                '@permissions': '111111100'
              };
              acl.push(aclObject);
            };
          };
          return acl;
        },
        '@type': "document",
        '@action': "create",
      };
      nodeArray.push(nodeObject);
    };
    return nodeArray;
  }
};

// writing our elements in the xml file using the XML object:
var ele = xmlObjectImporter.ele(xmlObjectElement);

console.log(xmlObjectImporter.toString({
  pretty: true
}));

Here is an output I would expect from this: 这是我期望的输出:

<import>
  <node type="document" action="create">
    <location>Enterprise1</location>
    <category name="ACME">
      <attribute name="Document Number">3912271</attribute>
    </category>
    <docnumber>3912271</docnumber>
    <acl group="group1" permissions="111111100" />
    <acl group="group2" permissions="111111100" />
  </node>
  <node type="document" action="create">
    <location>Enterprise2</location>
    <category name="ACME">
      <attribute name="Document Number">3912298</attribute>
    </category>
    <docnumber>3912298</docnumber>
    <acl group="group3" permissions="111111100" />
    <acl group="group4" permissions="111111100" />
  </node>
  <node type="document" action="create">
    <location>Enterprise3</location>
    <category name="ACME">
      <attribute name="Document Number">3912692</attribute>
    </category>
    <docnumber>3912692</docnumber>
    <acl/>
  </node>
</import>

You have several undeclared variables that will cause your code to break when running in strict mode. 您有几个未声明的变量,它们将在严格模式下运行时导致代码中断。

  1. i and j in your for loops both need declared. 您的for循环中的ij都需要声明。 eg let i = 0 . 例如let i = 0
  2. The aclObject is not declared. 未声明aclObject You need to add a var declaration, eg const aclObject = { ... } . 您需要添加一个var声明,例如const aclObject = { ... }

After fixing those, I had no trouble running your code, at least, I had no trouble building the xmlObjectElement and executing the node() and acl() functions, which worked. 修复这些问题之后,至少可以顺利运行代码,至少可以轻松构建xmlObjectElement并执行有效的node()和acl()函数。

UPDATED 更新

This will not fix the way that xml-builder is traversing your object and building the xml, but your functions could be improved by using Array methods instead of for loops. 这不会解决xml-builder遍历对象并构建xml的方式,但是可以通过使用Array方法而不是for循环来改善您的功能。 You'd have no need to use i or j and decrease the chances of introducing a bug for that reason. 因此,您无需使用ij并减少引入错误的机会。

For instance, you could easily replace both loops with a use of .map() . 例如,您可以使用.map()轻松替换两个循环。 See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map . 请参阅https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/map

var xmlObjectElement = {
  node: function () {
    return documentsJSON.map((document) => {
      // populate the nodeObject for each row in documentsJSON and add it to the nodeArray:
      return {
        location: document.folder,
        category: {
          attribute: [
            { '#text': document.docnumber, '@name': "Document Number" }
          ],
          '@name': "ACME",
        },
....
})

Following nxSolari's suggestion, I re-wrote the code using 2 functions instead of a big object and methods and got the desired result. 按照nxSolari的建议,我使用2个函数而不是大对象和方法重新编写了代码,并获得了预期的结果。 I still don't understand how the code gets through the objects and methods, but here is the new working code: 我仍然不了解代码如何通过对象和方法,但是这里是新的工作代码:

    'use strict';

    var documentsJSON = [{
        "folder":"Enterprise1" , 
        "extension":"DOCX" , 
        "docnumber":"3912271" , 
        "version":"1"
        },
        {
        "folder":"Enterprise2" , 
        "extension":"MSG" , 
        "docnumber":"3912298" , 
        "version":"1"
        },
        {
        "folder":"Enterprise3" , 
        "extension":"DOCX" , 
        "docnumber":"3912692" , 
        "version":"1"
        }
    ]

    var GroupsACLJSON = [{
        "docNumber":"3912271" , 
        "groupName":"group1"
        },
        {
        "docNumber":"3912271" , 
        "groupName":"group2"
        },
        {
        "docNumber":"3912298" , 
        "groupName":"group3"
        },
        {
        "docNumber":"3912298" , 
        "groupName":"group4"
        },
        {
        "docNumber":"3912692" , 
        "groupName":"group5"
        }
    ]


    // importing and declaring xmlbuilder variable: 
    var builder = require('xmlbuilder');
    var xmlObjectImporter = builder.create('import', {
        version: '1.0', 
        encoding: 'UTF-8', 
        standalone: true
    }, {
        headless: false, 
        stringify: {}
    });

    var xmlObjectElement = {};

    function buildACLnode(passedDoc, acls) {
        var acl= [];
        for (var jDoc = 0 ; jDoc < acls.length ; jDoc++) {
            if (acls[jDoc].docNumber == passedDoc) {
                var aclObject = {
                    '@group':  acls[jDoc].groupName,
                    '@permissions': '111111100'
                };
                acl.push(aclObject);
            };
        };
        return acl;
    }

    function buildXML(documents) {
        var nodeArray = [];
        for (var iDoc = 0; iDoc < documents.length; iDoc++) {
            var nodeObject = {
                    node: {
                        location: documentsJSON[iDoc].folder,
                        category: {
                            attribute: [
                                { '#text': documentsJSON[iDoc].docnumber, '@name': "Document Number" }
                                ],
                            '@name': "ACME",
                        },
                        acl: buildACLnode(documentsJSON[iDoc].docnumber, GroupsACLJSON),
                        '@type': "document",
                        '@action': "create",
                        }
                };
            nodeArray.push(nodeObject);
        };
        return nodeArray;
    }

    xmlObjectElement = buildXML(documentsJSON);

    // writing our elements in the xml file using the XML object:
    var ele = xmlObjectImporter.ele(xmlObjectElement);

    console.log(xmlObjectImporter.toString({ 
        pretty: true 
    }));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM