代码之家  ›  专栏  ›  技术社区  ›  RobVious

只通过传递财产来修改JS对象的财产?

  •  0
  • RobVious  · 技术社区  · 12 年前

    我正在构建一个插件,它接受两个参数-高度和宽度。此插件的使用者可能有一个矩形对象、一个正方形对象或一个多边形对象等。其宽度/高度的名称可能不同:

    var square = { 
       width: 200,
       height: 200
    }
    
    var rectangle = { 
       Width: 200,
       tall: 200
    }
    
    var polygon = { 
       w: 200,
       h: 200
    }
    

    我正在尝试构建一个接受宽度/高度参数并修改它们的函数,以便更新父对象。类似于:

    var alterStuff = function (width, height){
        width = 200;
        height = 200;
    };
    
    var obj = {width: "28", height: "34"};
    
    alterStuff(obj.width, obj.height);
    
    alert(obj.width);
    

    目标是消费者可以传递两种基本类型 alterStuff 函数将在对象上更新它们。

    可以使用什么模式来实现这一点?现在 obj 财产没有被更新-我在警报中看到“28”,但我希望看到“200”而不传递对象,因为我不知道在所有情况下该对象上的属性名称是什么。

    3 回复  |  直到 12 年前
        1
  •  4
  •   Tibos    12 年前

    简短的回答:你不能!

    当你向函数传递一些东西时,你会传递它的值。如果它是原始值,例如5,则将5传递给函数。如果它是一个对象,实际上它是对一个对象的引用,然后传递该引用。这意味着当你通过 obj.width 例如,它的值 45px 只将该字符串传递给函数 obj .

    更新对象财产的唯一方法是传递对象本身和属性名称:

    function change(obj, key, val) {
      obj[key] = val;
    }
    
    var obj = { width : 5 };
    change(obj, 'width', 10);
    

    在您的特定情况下,您可以尽最大努力从对象的键“猜测”属性名称。在下面的示例中,widthKey和heightKey是可选的,因此如果库函数的用户有一个行为良好的对象,他不需要传递它们。否则,他应该通过他们。

    function updateSize(object, width, height, opt_widthKey, opt_heightKey) {
      // potential width properties:
      var widths = ['width', 'Width', 'w'];
      // potential height properties:
      var heights = ['height', 'Height', 'h'];
    
      var widthKey = opt_widthKey || getPropertyName(object, widths);
      if (!widthKey) throw new Error('Can not guess width property');
    
      var heightKey = opt_heightKey || getPropertyName(object, heights);
      if (!heightKey) throw new Error('Can not guess height property');
    
      object[widthKey] = width;
      object[heightKey] = height;
    }
    
    function getPropertyName(object, properties) {
      for (var i=0; i<properties.length; i++) {
        if (object.hasOwnProperty(properties[i]))
          return properties[i];
      }
    }
    
    // usage:
    
    var obj = { width : 5, Height : 10 };
    var notGood = { tall : 20, wide : 40 };
    
    updateSize(obj, 100, 200);
    updateSize(notGood, 100, 200, 'wide', 'tall');
    
        2
  •  0
  •   Danilo Valente    12 年前

    您必须传递对象本身,而不是其财产:

    var alterStuff = function (obj){
        obj.width = 200;
        obj.height = 200;
    };
    
    var obj = {width: "28", height: "34"};
    
    alterStuff(obj);
    

    你可能想读 this article .

        3
  •  0
  •   Matt Burland    12 年前

    我认为没有一个好的方法可以在不传递对象的情况下做你想做的事情。也许您可以返回一个2成员数组,调用者将负责将其加载回正确的位置:

    var alterStuff = function(width, height) {
        return [+width * 2, +height * 2];    // for example
    }
    
    var obj =  {width: "28", height: "34"};
    
    var newValues = alterStuff(obj.width, obj.height);
    obj.width = newValues[0];
    obj.height = newValues[1];
    

    或者,您可以让调用者提供回调函数:

    var alterStuff = function(width, height, callback) {
        // note: you may want to include some checks for undefined and that callback is a function
        callback(+width *2, +height * 2);
    }
    
    alterStuff(obj.width, obj.height, function(width, height) {
       obj.width = width;
       obj.height = height;
    });
    

    所以现在如果我有:

    var rectangle = { 
       Width: 200,
       tall: 200
    }
    

    我可以打电话 alterStuff 这样地:

    alterStuff(rectangle.Width, rectangle.tall, function(Width, tall) {
        rectangle.Width = Width;
        rectangle.tall = tall;
    });
    

    我为“宽度”和“高度”(如财产)选择的名称是调用者的选择。

    或者Tibos的答案是另一种选择,即在调用函数时输入键。