2014-02-19 126 views
0

我正在构建一个插件,它接受两个参数 - 高度和宽度。这个插件的消费者可能有一个矩形对象,或方形物体,或多边形物体,等他们的宽度/高度的名称可能是不同的:通过仅传递属性来修改JS对象的属性?

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”而不传入对象,因为我不知道该对象上的属性名称是什么在所有情况下。

+0

你有固定的一组属性名称,这里给出的三个,或者它可以是任何东西? – chelmerich

+0

@chelmerich - 它可能是任何东西 – RobVious

回答

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

您可能需要阅读this article

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的答案是您调用该函数时传递密钥的另一种方法。