2014-02-19 168 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的答案是您調用該函數時傳遞密鑰的另一種方法。