简体   繁体   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

Scroll down to the bottom of this post to see a work around / possible solution. 向下滚动到这篇文章的底部,以查看解决方法/可能的解决方案。

This is probably easier just to explain in the source code with comments. 仅用注释在源代码中进行解释,这可能会更容易。 The issue at hand is I cannot figure out how pseudo classes work together to perform the task I'm trying to do (explained in the code below). 当前的问题是我无法弄清楚伪类如何协同工作来执行我要执行的任务(在下面的代码中进行了解释)。

The code is broken down into 3 files: lead.js, router.js, and db.js. 该代码分为3个文件:lead.js,router.js和db.js。

There are a decent amount of lines of code but most of it is comments. 有很多代码行,但大多数都是注释。

[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)
};

When I run this, my validator always reports that the password is empty which makes sense. 当我运行此命令时,验证程序将始终报告密码为空,这很有意义。 I'm sending the document initially to the class with an empty password (the password is randomly generated, not a form field) -- the problem is I have no idea what to do with the if (!document) ... code block to actually set the this.document properly. 我最初使用空密码将文档发送给类(密码是随机生成的,而不是表单字段)-问题是我不知道如何处理if(!document)...代码块正确地设置this.document。

I hope between the comments and code you can get an idea of what I'm trying to do. 我希望在注释和代码之间您可以了解我要做什么。 I've been stuck on this for a while. 我已经坚持了一段时间。

EDIT 编辑

I changed the flow of it a bit to get a solution. 我稍微改变了流程以获得解决方案。

In the db.js, I exported the connection rather than instantiating the lead (and future models) directly. 在db.js中,我导出了连接,而不是直接实例化线索(和将来的模型)。

In the router.js file, I require the db and lead file, then pass both the db connection and the document in the constructor of the Lead. 在router.js文件中,我需要db和Lead文件,然后在Lead的构造函数中传递db连接和文档。 Ex. 防爆。

var lead = new Lead(db, document);

In the lead.js file, it becomes as simple as doing this.document = document (same as the db). 在lead.js文件中,它变得像执行this.document = document(与db一样)一样简单。 When I submit a new lead, the values I don't send over from router.js get appended to the document (the created date, a random password, etc.) and everything is good. 当我提交新线索时,我没有从router.js发送的值会附加到文档中(创建日期,随机密码等),一切都很好。

Is this a decent way of handling this, or is there a better way to refactor this? 这是处理这个问题的一种体面的方法,还是有一种更好的方法来重构它?

This is completely wrong way even if make this code work as you want. 即使使此代码按需工作,这也是完全错误的方法。 In this example you have singleton lead. 在此示例中,您具有单身领导。 By requesting /register url you want to set 'document' field to this singleton . 通过请求/ register url,您想要将'document'字段设置为此单例。 (IMPORTANT) But requests work asynchronously. (重要)但是请求异步工作。 Absolutely no guarantee that you save the document, which has just validate. 绝对不能保证您保存的文档刚刚生效。 Because new request may overwrite it in lead object. 因为新的请求可能会覆盖潜在客户中的对象。 You need to do this logic in request scope. 您需要在请求范围内执行此逻辑。 One scope for one request. 一个请求的一个范围。 Not one for all. 并非一无所有。

You set var document = {} initially, and {} is not falsy. 您最初设置var document = {} ,而{}并非虚假。 Better would be to set as a starting value document = null and then after checking for !document set document = {} before assigning whatever properties you need. 最好将其设置为起始值document = null ,然后在检查!document set document = {}之后,再分配所需的任何属性。

You need to read up on object-oriented programming in Javascript . 您需要阅读Javascript中的面向对象编程

The anonymous function you're defining near the top of your code is the constructor function, so with respect to the document property you want that is currently uninitialized, just type something like: 您在代码顶部附近定义的匿名函数构造函数,因此对于您希望当前未初始化的document属性,只需键入以下内容:

this.document = null;

Then some time later when you create a new object using this constructor, like so: 然后一段时间后,当您使用此构造函数创建新对象时,如下所示:

var myLead = new Lead(dbConnection);

You'll have the myLead.document property. 您将拥有myLead.document属性。

There are many other things wrong with your code, though. 但是,您的代码还有很多其他问题。 Why are you assuming that there is a global document variable with relevant data visible in your library when it's defined as {} ? 为什么要假设在定义为{}时在库中存在一个具有相关数据的全局document变量? The code in that if statement at the end of your constructor should be run when the document property is set in your other file below, and should only expect this.document to exist. 当在下面的其他文件中设置document属性时,应在构造函数末尾的if语句中运行代码,并且应仅希望this.document存在。

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

相关问题 我在使用setInterval和类方法时遇到了很多麻烦 - I'm having a lot of trouble with setInterval and class methods 尝试在图像之间切换时,Javascript Onclick事件有点麻烦 - I'm having a bit of trouble with the Javascript Onclick event when trying to toggle between images 我在搜索对象并使用Javascript的indexOf()函数在表上显示结果时遇到麻烦 - I'm having trouble with searching through an object and displaying the result on table using Javascript's indexOf() function 我正在尝试将对象键“品牌”及其值放入一个新数组中,但我遇到了麻烦 - I’m trying to get the object key “brand” and its value into a new array but I’m having trouble 我在尝试拼接数组时遇到问题 - I'm having trouble trying to splice an array 我在理解此Javascript函数时遇到问题 - I'm having trouble understanding this Javascript function 我在用JavaScript读取Cookie时遇到问题 - I'm having trouble reading a cookie in javascript 我在从 NestJS 上已导入的模块导入服务时遇到问题 - I'm having trouble importing a service from an already imported module on NestJS 我正在尝试使用JavaScript在HTML网页上创建动态菜单,但是仍然遇到麻烦 - I'm trying to create a dynamic menu on a HTML web page using JavaScript, but keep having trouble 我在输出JavaScript时遇到问题 - I'm having trouble having my JavaScript output
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM