0

我有一个带有很多可以修改内部状态的函数的 JavaScript 对象,我想将所有这些函数移动到一个外部文件中。有一个最佳实践来做到这一点?主要对象是飞机,当飞机飞行时会发生很多情况。对于每种情况,我都有一个功能可以改变飞机的内部状态(ae改变发动机的当前速度)。这些函数被命名为situation1、situation2、...situationN。我想把所有这些函数放在一个 kind o 库中。这是正确的和/或可能的吗?这是一个示例代码

function Engine(){
    this.state = 'off';
    this.currentSpeed = 0;
}

function Airplane(){
    this.engine1 = new Engine();
    this.engine2 = new Engine();
}

Airplane.prototype.fly = function(){
    //this is for example
    var randomnumber=Math.floor(Math.random()*101);
    switch (randomnumber) {
        case 1: this.situation1();break;
        case 2: this.situation2();break;
        // ...
        case 100: this.situation100();break;            
    }
    this.fly();
}

Airplane.prototype.situation1 = function() { /*change internal state of an Engine* a.e: */ this.engine1.currentSpeed = '200'; }
Airplane.prototype.situation2 = function() { /*change internal state of Engine* a.e: */ this.engine1.currentSpeed = 200 * 3.14; }
// ...
Airplane.prototype.situation100 = function()  { /*change internal state of Engine*/ this.engine2.state = 'on';}


airplane = new Airplane();
airplane.fly();
4

1 回答 1

0

我相信您正在寻找的是 node.js 所指的“模块”,在http://nodejs.org/api/modules.html中有解释

一种方法是创建一个名为“Airplane.js”的新文件,其中包含:

// define your main object
var Airplane = function(){
    // initialize it here
};

Airplane.funcOne=function(){ // "class" level function
};

Airplane.prototype.funcTwo=function(){ // "instance" level function
};

// assign Airplane to module exports 
module.exports=Airplane;

// which allows you to:
//     var Airplane=require('Airplane');

如果您不希望在其他代码中使用您的引擎,您可以在 Airplane.js 中定义它。

如果您希望您需要从其他代码中“要求”它,您可能希望将其放入它自己的文件中并在 Airplane.js 中“要求”它,例如:

// Engine.js
var Engine=function(){
};

module.exports=Engine;

// Airplane.js
var Engine=require('Engine');

var Airplane=function(){
};

module.exports=Airplane;

最后,如果您想从同一个文件中同时公开 Airplane 和 Engine,您可以:

var Engine=function(){
};

var Airplane=function(){
};

module.exports={
    Engine:   Engine,
    Airplane: Airplane
};

因此,当您在另一个文件中需要 Airplane 时,您会说:

var Airplane = require('Airplane').Airplane,
    Engine   = require('Airplane').Engine;

更新

作为记录,我不赞成在定义对象的文件之外定义对象的原型方法,但话虽如此......

将另一个文件中定义的方法添加到现有对象需要您“需要”附加文件,迭代其函数,并将它们添加到现有对象。

最简单的方法是将您的方法定义为:

// file: AirplaneMethods.js

module.exports={

    // what occurs in situation1
    situation1: function(){

        // as expected, 'this' within this method refers 
        // to the object into which this method is "imported."

        return this; // to facilitate method chaining
    },

    // what occurs in situation2
    situation2: function(){
        // ...
        return this; 
    }

    // etc.
};

然后,要将这些方法添加到您的 Airplane 对象,您将:

var Airplane=function(){
    // initialization
};

var importedMethods=require('AirplaneMethods');

for(var methodName in importedMethods) {
    Airplane.prototype[methodName]=importedMethods[methodName];
}

或者对于更通用的解决方案:

/* Import.js -- 20130712 raisch
 *
 * imports methods defined in one or more external paths into an
 * existing object's prototype
 *
 * Usage:
 *
 *     var Import=require('Import');
 *
 *     var Thing=function() {};
 *
 *     Import.from(path1,path2,...).into(Thing);
 *
 *     -or-
 *
 *     Import.into(Thing).from(path1,path2,...)
 *
 */

var util=require('util'),
    assert=require('assert');

var Import=module.exports=function(){};

Import._target=null;

Import._libs={};

// shortcut
var hasOwnProperty=Object.prototype.hasOwnProperty;

// helper
function isEmpty(obj){
    var result=true;
    if(obj===null || 0===obj.length) {
        result=true;
    }
    else if(obj.length && obj.length>0) {
        result=false;
    }
    else {
        for(var k in obj) {
            if(hasOwnProperty.call(obj,k)) {
                result=false;
                break;
            }
        }
    }
    return result;
}

/**
 * requires one or more libs, caching them into self._libs
 *
 * if self._target is not null, calls self.into() to add all lib
 * methods to self._target.prototype
 *
 * @param paths {Array<String>}
 * @returns {Object} self
 */
Import.from=function from(/*path,...*/){
    var paths=Array.prototype.slice(arguments);
    for(var i=0, len=paths.length; i<len; i++){
        var path=paths[i],
            lib=null;
        try{
            lib=require(path);
            if(isEmpty(lib)){
                throw 'requiring "'+path+'" did not produce a useful object';
            }
        }
        catch(e){
            console.error('Import.from failed to require path "%s":%s', path, e);
            continue;
        }
        this._libs[path]=lib;
    }
    this._target && this.into(this._target);
    return this;
};

/**
 * sets target object (class) into which to import lib methods
 *
 * if self._libs is not empty, adds all lib methods to self._target.prototype
 *
 * @param target {Object} into which to import
 * @returns {Object} self
 */
Import.into=function into(target){
    assert.ok(target.prototype, 'Import.into: target must have a prototype');
    this._target=target;
    if(!isEmpty(this._libs)){
        for(var libname in this._libs){
            var lib=this._libs[libname];
            for(var name in lib){
                this._target.prototype[name]=lib[name];
            }
        }
    }
    return this;
};

/**
 * clears library cache
 * @returns {Object} self
 */
Import.clear=function clear(){
    this._libs={};
    return this;
};

/**
 * clears library cache and target object
 * @returns {Object}
 */
Import.reset=function reset(){
    delete this._target;
    this.clear();
    return this;
};
于 2013-07-09T21:02:02.233 回答