通过仅传递属性来修改JS对象的属性?

时间:2014-02-19 15:21:07

标签: javascript jquery

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

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 个答案:

答案 0 :(得分:4)

简短的回答:你不能!

当你将某些东西传递给一个函数时,你会传递它的值。如果它是原始值,例如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');

答案 1 :(得分:0)

您必须传递对象本身而不是其属性:

var alterStuff = function (obj){
    obj.width = 200;
    obj.height = 200;
};

var obj = {width: "28", height: "34"};

alterStuff(obj);

您可能需要阅读this article

答案 2 :(得分:0)

我不认为有一种很好的方法可以在不传递对象的情况下做你想做的事。也许您可以返回一个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的回答是另一种选择,当你调用函数时传入密钥。