Изменение свойств объекта JS путем передачи только свойств?

0

Я создаю плагин, который принимает два параметра - высоту и ширину. Пользователи этого плагина могут иметь объект прямоугольника или квадратный объект или объект многоугольника и т.д. Имена их ширины/высоты могут быть разными:

var square = { 
   width: 200,
   height: 200
}

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

var polygon = { 
   w: 200,
   h: 200
}

Я пытаюсь создать функцию, которая принимает параметры width/height и изменяет их, чтобы обновлялся родительский объект. Что-то вроде этого:

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" без передачи в объект, так как я не знаю, какие имена свойств будут на этом объекте в любом случае.

  • 0
    У вас есть фиксированный набор имен свойств, три, приведенные здесь, или это может быть что-нибудь?
  • 0
    @chelmerich - это может быть что угодно
Теги:

3 ответа

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');
0

Вам придется передать сам объект, а не его свойства:

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

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

alterStuff(obj);

Вы можете прочитать эту статью.

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;
});

И какие имена я выбираю для свойств "ширина" и "высота", это выбор вызывающих.

Или ответ Тибоса - это еще одна альтернатива, когда вы передаете ключ (ы), когда вы вызываете функцию.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню