【问题标题】:Can you create an object in Javascript without declaring every value, and how?您可以在不声明每个值的情况下在 Javascript 中创建一个对象吗?如何?
【发布时间】:2015-02-23 17:34:51
【问题描述】:

我想做以下事情:

var Room = function(name, north, south, east, west) {
    this.name = name;
    this.north = north;
    this.south = south;
    this.west = west;
    this.east = east;
}

哪里有北、南、东、西,只是一面旗帜,表明那里是否有门。

当我创建一个对象时,我必须这样做:

var bedroom = new Room('Bedroom', true, false, false, false);

我想知道是否有办法让我可以说出哪些方向具有真实价值,例如:

var bedroom = new Room({
    name: 'Bedroom',
    north: true
});

south, east, and west 都变成了 false。 这样,如果我要说 20 个不同的选项,我只需要指定我关心的选项,而不是用冗长的声明很多 false 和 '' 值,我不需要记住它们应该处于哪个顺序(北、南、东、西?还是北、东、南、西?),

【问题讨论】:

    标签: javascript variables object declaration


    【解决方案1】:

    如果您确实需要 northsoutheastwest 的单独实例变量,我建议您使用类似这样的方法,您可以在空格分隔的字符串中传递您关心的方向.这使得调用代码更加简单,因为您不必为不存在的方向传递任何内容。

    var Room = function(name, directions) {
        this.name = name;
        this.north = this.south = this.west = this.east = false;
        directions = directions.split(" ");
        directions.forEach(function(item) {
            this[item] = true;
        })
    }
    
    var bedroom = new Room('Bedroom', 'north south');
    

    或者,您的对象方法也可以正常工作:

    var Room = function(name, directions) {
        this.name = name;
        this.north = this.south = this.west = this.east = false;
        for (var dir in directions) {
            this[dir] = directions[dir];
        }
    }
    
    var bedroom = new Room('Bedroom', {north: true, south: true});
    

    第三种方法是使用标志(通常在 C/C++ 中使用)。这允许您在单个值中传递任意数量的标志:

    var Room = function(name, directions) {
        this.name = name;
        this.directions = directions;
    }
    
    Room.prototype = {
       isNorth: function() { return this.directions & Room.north},
       isSouth: function() { return this.directions & Room.south},
       isWest: function() { return this.directions & Room.west},
       isEast: function() { return this.directions & Room.east},
    };
    
    Room.north = 1;
    Room.south = 2;
    Room.east = 4;
    Room.west = 8;
    
    var bedroom = new Room('Bedroom', Room.north | Room.south);
    

    【讨论】:

    • 如果南北都应该是真的呢?
    • @j08691 - 我最初并没有意识到这是一个要求。我已经修改了我的答案以支持它。
    • 空格分隔的字符串有点特殊(也就是说,现在你在许多其他情况下都会这样做),但在这种情况下它有点可爱。
    • 谢谢,在尝试了其他的之后,这个似乎最适合我!
    • @JonathanOwenChute - 我添加了使用二进制标志的第三个版本。
    【解决方案2】:

    JavaScript 对象

    使用|| 运算符添加默认值

    var Room = function(name, north, south, east, west) {
        this.name = name;
        this.north = north || false;
        this.south = south || false;
        this.west = west || false;
        this.east = east || false;
    }
    

    如果为它提供了数据,这将告诉它使用 east,或者如果 east 原来是 undefined,则使用 false。

    【讨论】:

    • 我认为问题的重点是不必在构造函数中一次通过所有方向。这看起来确实有点傻。
    • 在使用truefalse 分配默认值时要小心。它会朝这个方向工作,但你不能以这种方式用真实的默认值分配错误的值。
    【解决方案3】:
    var Room = function (options) {
        this.name = options.name;
        var cardinals = ['north', 'south', 'east', 'west'];
    
        // Check your directions param for each of the cardinal directions
        // that you want to allow
        cardinals.forEach(function (direction) {
            if (typeof options[direction] !== 'undefined') {
                this[direction] = options[direction];
            } else {
                this[direction] = false;
            }
        });
    };
    
    var room = new Room({ name: 'Bedroom', north: true, south: true });
    

    【讨论】:

    • 不建议在 JavaScript 中使用 for (var direction in cardinals) 迭代数组,因为这会迭代数组的所有属性,不仅是数组元素,而且可能包括任何可枚举的 polyfill 方法或添加到 Array 对象的自定义方法.相反,请使用.forEach() 或样式for (var i = 0; i < cardinals.length; i++)
    • 同意!不知道为什么我最初使用这种方式;心不在焉?我已经为后代更新了我的示例。
    【解决方案4】:

    您可以使用“for .. in ...”循环来迭代带有参数的输入对象。示例:

    Room = function(options) {
        for (var key in options) {
            this[key] = options[key];
        }
    }
    
    var bedroom = new Room({
        name: 'Bedroom',
        north: true
    });
    

    【讨论】:

    • 我想一旦for .. of .. 在所有地方都得到支持,我就会改用这种方法。我喜欢任何其他值是undefined 的方式,但是使用for .. in .. 有问题。
    【解决方案5】:

    您可以使用|| 运算符

    例如

    var Room = function(name, directions) {
        this.name = name;
        this.north = directions.north || false;
        this.south = directions.south || false;
        this.west = directions.west || false;
        this.east = directions.east || false;
    }
    

    那么当您调用var r = new Room("something", {north:true}); 时,所有其他值都将设置为false。

    【讨论】:

      【解决方案6】:

      你可以使用某种子类。

      在主类中放置所有默认值。

      function AbstractRoom(name, north, south, east, west){
          this.name = name;
          this.north = north;
          this.south= south;
          this.east= east;
          this.west= west;
      }
      

      在你的子类中输入你的价值观

      function RoomNorth(name){
        AbstractRoom.call(this, name, true, false, false, false);
      }
      

      在这种情况下

      var myNorthRoom = new RoomNorth('AGoodName');
      

      在哪里

      myNorthRoom.north <-- true
      myNorthRoom.south <-- false
      

      【讨论】:

        【解决方案7】:

        怎么样:

        var Room = function( name, directions ) {
            this.name = name;
            this.north = directions.north || false;
            this.south = directions.south || false;
            this.west = directions.west || false;
            this.east = directions.east || false;
        }
        

        然后像这样调用构造函数:

        var bedroom = new Room( 'Bedroom', { 'north': true } );
        

        如果你没有定义一个方向 ||运算符会使其为假。

        【讨论】:

          【解决方案8】:

          这是使用“链接”模式的另一种方式(它本身不是构建器):

          function Room (name) {
             this.name = name;
          }
          
          Room.prototype = {
             north: function (v) {
                 if (arguments.length > 0 } { this._north = v; return this; }
                 else { return this._north; }
             },
             south: function (v) {
                 if (arguments.length > 0 } { this._south = v; return this; }
                 else { return this._south; }
             },
             // .. rest of getter-setters
             // The prototype can be used for defaults and/or lifting
             _north: false,
             _south: false,
             // .. rest of defaults
          }
          
          var room = new Room("bedroom")
            .north(true)
            .south(true); // => the Room object
          
          var hasNorth = room.north(); // => true
          

          有些人可能不喜欢这种模式——尤其是这种实现——因为它改变了 getter/setter 的返回类型为“sometimes-chainable”和“sometimes-return-the-value”,就像一些 jQuery 方法(例如$.val)。

          它还要求/鼓励通过 getter 方法访问方向(例如“北”)。定义属性不允许这样的链接语法。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-21
            • 2011-04-25
            • 1970-01-01
            相关资源
            最近更新 更多