【问题标题】:How to write a object oriented Node.js model如何编写面向对象的 Node.js 模型
【发布时间】:2014-05-02 17:55:36
【问题描述】:

我在 Node.js 中编写面向对象的 Cat 类时遇到了很多麻烦。如何编写一个 Cat.js 类并按以下方式使用它:

// following 10 lines of code is in another file "app.js" that is outside 
// the folder "model"
var Cat = require('./model/Cat.js');

var cat1 = new Cat(12, 'Tom');
cat1.setAge(100);
console.log(cat1.getAge()); // prints out 100 to console

var cat2 = new Cat(100, 'Jerry');
console.log(cat1.equals(cat2)); // prints out false

var sameAsCat1 = new Cat(100, 'Tom');
console.log(cat1.equals(sameAsCat1)); // prints out True

您将如何修复我编写的以下 Cat.js 类:

 var Cat = function() {
    this.fields = {
        age: null,
        name: null
    };

    this.fill = function (newFields) {
        for(var field in this.fields) {
            if(this.fields[field] !== 'undefined') {
                this.fields[field] = newFields[field];
            }
        }
    };

    this.getAge = function() {
        return this.fields['age'];
    };

    this.getName = function() {
        return this.fields['name'];
    };

    this.setAge = function(newAge) {
        this.fields['age'] = newAge;
    };

    this.equals = function(otherCat) {
        if (this.fields['age'] === otherCat.getAge() && 
            this.fields['name'] === otherCat.getName())  {
            return true;
        } else {
            return false;
        }
    };
};

module.exports = function(newFields) {
    var instance = new Cat();
    instance.fill(newFields);
    return instance;
};

【问题讨论】:

  • 这是否是唯一的问题,我不能说,但你想在你的fill 函数中测试typeof() !== 'undefined'。而且因为您为它们分配了null 值,所以无论如何这都行不通,因为您将在typeof 上获得“对象”。如果您只是将它们分配为undefined 并通过typeof() 进行测试,否则它看起来应该像您预期的那样运行。
  • 您需要帮助的具体问题是什么?
  • 您可能想看看TidBits OoJs。它是可靠的,并以简单自然的语法为您提供了您可能梦寐以求的所有 OO 功能,但多重继承除外。

标签: javascript node.js oop


【解决方案1】:

我会使用一个类:

class Cat {
    fields = {
        age: null,
        name: null
    };

    fill(newFields) {
        for(var field in this.fields) {
            if(this.fields[field] !== 'undefined') {
                this.fields[field] = newFields[field];
            }
        }
    }

    getAge() {
        return this.fields.age;
    }

    setAge(newAge) {
        this.fields.age = newAge;
    }
}

exports.Cat = Cat;

【讨论】:

  • 我来给同样的答案,看到这个-4答案,天哪。它有什么问题?
  • @Asqan 可能是因为问题要求的是 JS,而不是 TypeScript。而且你不能在浏览器中“使用”TypeScript,需要先编译成JS。
  • 我已经从答案中删除了 TypeScript,因为真正的现代 JavaScript 具有我推荐的功能(类)。
【解决方案2】:

此代码在此处运行良好的 Person.js 代码

  exports.person=function(age,name)
    {
        age=age;
        name=name;
        this.setAge=function(agedata)
        {
           age=agedata;
        }
        this.getAge=function()
        {
            return age;
        }
        this.setName=function(name)
        {
            name=name;
        }
        this.getName=function()
        {
            return name;
        }

};

调用对象代码:

var test=require('./route/person.js');
var person=test.person;
var data=new person(12,'murugan');
data.setAge(13);
console.log(data.getAge());
data.setName('murugan');
console.log(data.getName());

【讨论】:

    【解决方案3】:

    如果我要设计一个这样的对象,那么我会这样做

    function Cat(age, name) {       // Accept name and age in the constructor
        this.name = name || null;
        this.age  = age  || null;
    }
    
    Cat.prototype.getAge = function() {
        return this.age;
    }
    
    Cat.prototype.setAge = function(age) {
        this.age = age;
    }
    
    Cat.prototype.getName = function() {
        return this.name;
    }
    
    Cat.prototype.setName = function(name) {
        this.name = name;
    }
    
    Cat.prototype.equals = function(otherCat) {
        return otherCat.getName() == this.getName()
            && otherCat.getAge() == this.getAge();
    }
    
    Cat.prototype.fill = function(newFields) {
        for (var field in newFields) {
            if (this.hasOwnProperty(field) && newFields.hasOwnProperty(field)) {
                if (this[field] !== 'undefined') {
                    this[field] = newFields[field];
                }
            }
        }
    };
    
    module.exports = Cat;     // Export the Cat function as it is
    

    然后就可以这样使用了

    var Cat = require("./Cat.js");
    
    var cat1 = new Cat(12, 'Tom');
    cat1.setAge(100);
    console.log(cat1.getAge());                 // 100
    
    var cat2 = new Cat(100, 'Jerry');
    console.log(cat1.equals(cat2));             // false
    
    var sameAsCat1 = new Cat(100, 'Tom');
    console.log(cat1.equals(sameAsCat1));       // true
    
    var sameAsCat2 = new Cat();
    console.log(cat2.equals(sameAsCat2));       // false
    
    sameAsCat2.fill({name: "Jerry", age: 100});
    console.log(cat2.equals(sameAsCat2));       // true
    

    【讨论】:

    • @Chingy 我假设你的。尝试使用== 而不是=== :)
    • 或者现在在 ES6 中更好。
    【解决方案4】:

    @thefourtheye 的回答中存在错误漏洞,我将在下面进行描述

    对象建模规则

    • 创建空的新对象

    • 创建填充对象

    • 只有初始对象应该由机器/代码设置

    • 初始对象分配之后 对象中的任何更改都应仅通过用户交互发生。

    • 在初始对象分配之后,在没有用户意图的情况下通过代码对对象进行任何更改都会添加一些错误

    问题用例:

    例如 - 因此,当您创建填充对象时,如果任何属性(某个日期)没有任何值,那么由于下面的代码,默认值被分配给它(某个日期),这违反了对象建模规则。

    • 错误
    • 构造函数被赋予双重责任来创建新的 &填充对象,他在创建填充对象时混合在一起,并且 它会犯错误。
    • 意味着您的应用中有一些错误代码会在用户无意的情况下自行设置值

      function Cat(age, name, somedate ) { // Accept name and age in the constructor this.name = name || null; this.age = age || null; this.somedate = somedate || new Date(); //there will be lots of usecases like this }

    所以为了解决这个问题,我使用了下面的 JavaScript 数据模型。

    因此它允许用户仅在需要其中任何一个且不会相互混淆时有意地创建填充对象或新对象

    class Cat {
        constructor(){
            this.name = null;
            this.age = null;
        }
    
        initModel (data) {
            this.name = data.name;
            this.age = data.age
        }
    
        getAge () { return this.age;}
    
        setAge (age) { this.age = age; }
    
        getName () {this.name;}
    
        setName (name) {this.name = name;}
    
        equals (otherCat) {
            return otherCat.getName() == this.getName()
                && otherCat.getAge() == this.getAge();
        }
    
        fill (newFields) {
            for (let field in newFields) {
                if (this.hasOwnProperty(field) && newFields.hasOwnProperty(field)) {
                    if (this[field] !== 'undefined') {
                        this[field] = newFields[field];
                    }
                }
            }
        };
        
    }
    
    
    let cat1 = new Cat();
    cat1.initModel({age : 12,name :'Tom'})
    cat1.setAge(100);
    console.log(cat1.getAge());                 // 100
    
    let cat2 = new Cat();
    cat2.initModel({age : 100,name : 'Jerry'})
    console.log(cat1.equals(cat2));             // false
    
    let sameAsCat1 = new Cat({age : 100,name : 'Tom'});
    sameAsCat1.initModel({age : 100,name : 'Tom'})
    console.log(cat1.equals(sameAsCat1));       // true
    
    let sameAsCat2 = new Cat();
    console.log(cat2.equals(sameAsCat2));       // false
    
    sameAsCat2.fill({name: "Jerry", age: 100});
    console.log(cat2.equals(sameAsCat2)); 
    • 注意:
    • Constructor 仅用于创建 new Object
    • InitModel 仅用于创建填充对象

    注意在投反对票之前,请在 cmets 中添加您的疑问

    【讨论】:

      最近更新 更多