在JavaScript / Node.js中思考OOP

Thinking OOP in JavaScript / Node.js

本文关键字:OOP js JavaScript Node      更新时间:2023-09-26

我很了解JavaScript中OOP和原型继承的概念,但有时,我想知道如何在现实世界的应用程序中使用它们。

我将以几个月前我在GitHub上发布的一个简单的(istic)联系人管理web应用程序为例。

在主句柄中主要驻留函数:

var UserModel = require('../models/userModel.js');
var checkObjectId = new RegExp('^[0-9a-fA-F]{24}$');
var root;
exports.getContacts = function(request, response) {
    var id = JSON.parse(request.params.user)[0];
    // validate
    if (!checkObjectId.test(id)) {
        return res.status(400).json({error: 'Not a user id'});
    }
    UserModel.findById(id, function(err, user) {
        if (err) {
            return console.log(err);
        }
        response.send(user.contacts);
    });
};
exports.addContact = function(request, response) {
    var id = JSON.parse(request.params.user)[0];
    // validate
    if (!checkObjectId.test(id)) {
        return res.status(400).json({error: 'Not a user id'});
    }
    UserModel.findById(id, function(err, user) {
        if (err) {
            return console.error(err);
        }
        var contact = {};
        // avoid to save empty info
        if (request.body.first.length > 1) {contact.first = request.body.first;}
        if (request.body.last.length > 1) {contact.last = request.body.last;}
        if (request.body.mobile.length > 1) {contact.mobile = request.body.mobile;}
        if (request.body.home.length > 1) {contact.home = request.body.home;}
        if (request.body.office.length > 1) {contact.office = request.body.office;}
        if (request.body.email.length > 1) {contact.email = request.body.email;}
        if (request.body.company.length > 1) {contact.company = request.body.company;}
        if (request.body.description.length > 1) {contact.description = request.body.description;}
        if (request.body.keywords.length > 1) {contact.keywords = request.body.keywords;}
        user.contacts.push(contact);
        user.save(function(err) {
            if (err) {
                return console.error(err);
            }
            console.log('contact saved');
            response.send(user.contacts);
        });
    });
};
exports.updateContact = function(request, response) {
    var id = JSON.parse(request.params.user)[0];
    // validate
    if (!checkObjectId.test(id)) {
        return res.status(400).json({error: 'Not a user id'});
    }
    var contact = {
        _id: request.body._id,
        first: request.body.first,
        last: request.body.last,
        mobile: request.body.mobile,
        home: request.body.home,
        office: request.body.office,
        email: request.body.email,
        company: request.body.company,
        description: request.body.description,
        keywords: request.body.keywords
    };
    UserModel.update({_id: id, "contacts._id": request.body._id}, {$set: {"contacts.$": contact}}, function(err, user) {
        if (err) {
            return console.error(err);
        }
        response.sendStatus(user);
    });
};
exports.deleteContact = function(request, response) {
    var id = JSON.parse(request.params.user)[0];
    // validate
    if (!checkObjectId.test(id)) {
        return res.status(400).json({error: 'Not a user id'});
    }
    return UserModel.update({_id: id}, {$pull: {contacts: {_id: request.params.id}}}, function(err, user) {
        if (err) {
            return console.error(err);
        }
        console.log('contact removed');
        console.log(user);
        response.sendStatus(user);
    });
};

它不做太多:从DB获取数据并返回它们或从用户获取数据并将它们保存到DB。

如果它稍微复杂一点,我肯定会在单独的函数中放置一些逻辑以重用它们并分解复杂性。

尽管如此,这段代码看起来相当程序化,假设的具有单独函数的更复杂版本也是如此。它将如何以面向对象的方式组织,我将如何从中获益?

例如,我能从User构造函数中获益吗?

我认为你可以做的第一件事就是在初始化函数中嵌套构造函数的实例,这样你就不必重复验证代码了。

var connection = (function() {
  var UserModel = require('../models/userModel.js');
  var notAUser = {error: 'Not a user id'};
  function init(request, response) {   
    var status = validate(JSON.parse(request.params.user)[0]);
    if (!status.id) return response.status(400).json(status);
    return new Connect(request, response, status.id);
  }
  function Connect(request, response, id) {
    this.request = request;
    this.response = response;
    this.id = id;
    this.info = { _id: id, "contacts._id": request.body._id };
  }
  function validate(id) {
    if (!/^[0-9a-fA-F]{24}$/.test(id)) return notAUser;
    else return {id: id};
  }
  Connect.prototype.getContact = function() {} 
  //etc...
  return init;
})();
module.exports = connection;

那么在实际的应用程序中

var connection = require("./connection.js");
someAsync(data, function(req, res) {
    var query = connection(req, res); //returned instance of constructor
    query.getContact(someData, callback);    
});

我将首先封装requestresponse,因为每个方法都需要它们。如:

var contact = function (request, response) {
    return {
        add: add
    }
    function add() {
        // add() gets access request and response for free
    }
};

或者,如果您热衷于新的运算符:

function Contact(request, response) {
    this.request = request;
    this.response = response;
}
Contact.prototype.add = function () {
    this.request;
}

然后将重复的代码和回调移动到可以在对象内部重用的私有方法中。