繁体   English   中英

我已经在尝试初始化伪JavaScript类中的“ this”对象时遇到很多麻烦

[英]I'm having a lot of trouble trying to modify a “this” object from within a pseudo javascript class when it's already been initialized

向下滚动到这篇文章的底部,以查看解决方法/可能的解决方案。

仅用注释在源代码中进行解释,这可能会更容易。 当前的问题是我无法弄清楚伪类如何协同工作来执行我要执行的任务(在下面的代码中进行了解释)。

该代码分为3个文件:lead.js,router.js和db.js。

有很多代码行,但大多数都是注释。

[lead.js]

var bcrypt = require('bcrypt'),
    validators = require('../lib/validators'),
    utility = require('../lib/utility'),
    document = {};

var Lead = module.exports = function (db) {
  // Save a reference to the database.
  this.db = db;

  // Reference initial document.
  // This is totally wrong, not sure how to 'send' a variable to the constructor of a class
  // when I cannot add another param. Due to how I'm importing the db model, I won't know what
  // the document is until I fill out the form. I've also tried 'document' instead of 'Lead.document'.
  this.document = Lead.document;

  // Setup the document if it exists.
  // This also doesn't work.
  // Basically I want to be able to set up a document variable outside of this module (line #100),
  // Then pass it to this module after filling it up with values from a form.
  // Then based on what's been filled in, it would fix up (trim, convert to lower case)
  // some of the values automatically and default a few values that I'm not always going to pass.
  if (!document) {
    var salt = bcrypt.genSaltSync(10),
        hash = bcrypt.hashSync(utility.generatePassword(), salt);

    // Default values.
    if (!document.meta.createdAt) { this.document.meta.createdAt = Date.now(); }
    if (!document.login.password) { this.document.login.password = hash; }
    if (!document.login.role) { this.document.login.role = 'User'; }

    // Normalize a few values.
    this.document.login.email = document.login.email.toLowerCase().trim();
    this.document.contact.name.first = document.contact.name.first.trim();
    this.document.contact.name.last = document.contact.name.last.trim();
    this.document.contact.address.street = document.contact.address.street.trim();
    this.document.contact.address.city = document.contact.address.city.trim();
    this.document.contact.address.state = document.contact.address.state.trim();
    this.document.contact.address.zip = document.contact.address.zip.trim();
    this.document.contact.phone.home = document.contact.phone.home.trim();
  }
  // So in regards to the above code, the end result I'm looking for is...
  // I want to append some properties to the this.document reference when the document is empty (when I'm updating it, I won't set the document), 
  // and on new documents it will append a few default values/normalize all the fields.
};

Lead.prototype.validate = function(fn) {
  var errors = [];

  // Some validation rules I cut out to make this shorter.

  if (errors.length) return fn(errors);
  fn();
};

Lead.prototype.save = function(fn) {
  this.db.collection('leads', function(err, collection) {
    if (err) { fn(new Error({message: err})); }

    collection.insert(this.document, function(err, result) {
      return fn(err, result);
    });
  });
};

---

[route.js file]

  var db = require('../models/db');

  app.post('/register', function(req, res) {
    var data = req.body.lead || {};

    // Fill the document.
    var document = {
      meta: {
        host: req.headers.host,
        referer: req.headers.referer,
        createdIPAddress: req.connection.remoteAddress
      },
      login: {
        email: data.email
      },
      contact: {
        name: {
          first: data.first,
          last: data.last
        },
        address: {
          street: data.street,
          city: data.city,
          state: data.state,
          zip: data.zip
        },
        phone: {
          home: data.phone
        }
      }
    };

    // Write the document.
    db.lead.document = document;

    db.lead.validate(function(err) {
      if (err) {
        req.session.error = err;
        return res.redirect('back');
      }

      db.lead.save(function(err) {
        res.redirect('/register/success');
      });
    });
  });

---
[db.js]

var mongodb = require('mongodb'),
    server = new mongodb.Server('localhost', 27017),
    connection = new mongodb.Db('test', server);

connection.open(function(err, db) {});

module.exports =  {
  lead: new (require('./lead'))(connection)
};

当我运行此命令时,验证程序将始终报告密码为空,这很有意义。 我最初使用空密码将文档发送给类(密码是随机生成的,而不是表单字段)-问题是我不知道如何处理if(!document)...代码块正确地设置this.document。

我希望在注释和代码之间您可以了解我要做什么。 我已经坚持了一段时间。

编辑

我稍微改变了流程以获得解决方案。

在db.js中,我导出了连接,而不是直接实例化线索(和将来的模型)。

在router.js文件中,我需要db和Lead文件,然后在Lead的构造函数中传递db连接和文档。 防爆。

var lead = new Lead(db, document);

在lead.js文件中,它变得像执行this.document = document(与db一样)一样简单。 当我提交新线索时,我没有从router.js发送的值会附加到文档中(创建日期,随机密码等),一切都很好。

这是处理这个问题的一种体面的方法,还是有一种更好的方法来重构它?

即使使此代码按需工作,这也是完全错误的方法。 在此示例中,您具有单身领导。 通过请求/ register url,您想要将'document'字段设置为此单例。 (重要)但是请求异步工作。 绝对不能保证您保存的文档刚刚生效。 因为新的请求可能会覆盖潜在客户中的对象。 您需要在请求范围内执行此逻辑。 一个请求的一个范围。 并非一无所有。

您最初设置var document = {} ,而{}并非虚假。 最好将其设置为起始值document = null ,然后在检查!document set document = {}之后,再分配所需的任何属性。

您需要阅读Javascript中的面向对象编程

您在代码顶部附近定义的匿名函数构造函数,因此对于您希望当前未初始化的document属性,只需键入以下内容:

this.document = null;

然后一段时间后,当您使用此构造函数创建新对象时,如下所示:

var myLead = new Lead(dbConnection);

您将拥有myLead.document属性。

但是,您的代码还有很多其他问题。 为什么要假设在定义为{}时在库中存在一个具有相关数据的全局document变量? 当在下面的其他文件中设置document属性时,应在构造函数末尾的if语句中运行代码,并且应仅希望this.document存在。

暂无
暂无

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

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