问题:如何在不创建新对象引用的情况下将对象“扩展”。
提要:JQuery扩展功能可以做到。
但是如果使用的jquery.extend版本返回一个新对象,则该新对象就是一个新对象。很好,但是如果我在将引用传递给要扩展的对象的函数中进行扩展,则原始对象将保持不变。一个等待陷阱的好陷阱(我)。您知道对象是passed by reference-对吗?
示例代码:说我有一个对象
myObject = {
fontFamily : 'Tahoma',
fontSize: '12',
color : '000000'
}
和默认选项
myDefaults = {
fontFamily : 'Tahoma',
fontSize: '15',
color : 'FF0000',
weight : 'bold',
decoration : 'underline'
}
我的预期结果是:
myObject = {
fontFamily : 'Tahoma',
fontSize: '12',
color : '000000',
weight : 'bold',
decoration : 'underline'
}
所以这是代码:
var myObject = {
fontFamily : 'Tahoma',
fontSize: '12',
color : '000000'
}
$('#myObjectIn').html(JSON.stringify(myObject));
extenderoony(myObject);
$('#myObjectOut').html(JSON.stringify(myObject));
function extenderoony(obj){
var myDefaults = {
fontFamily : 'Tahoma',
fontSize: '15',
color : 'FF0000',
weight : 'bold',
decoration : 'underline'
}
obj = $.extend({}, obj, myDefaults); // << Changes the object reference of obj to a new object leaving the original object passed in as the parameter unchanged.
$('#obj').html(JSON.stringify(obj));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >Before the extend func</div>
<div id='myObjectIn'></div>
<hr>
<div >Inside the extend func</div>
<div id='obj'></div>
<hr>
<div >After the extend func</div>
<div id='myObjectOut'></div>
我的回答感觉很客气-我将在下面发布。
这是我的答案-与该问题相同的基本代码段,并带有注释。
var myObject = {
fontFamily : 'Tahoma',
fontSize: '12',
color : '000000'
}
$('#myObjectIn').html(JSON.stringify(myObject));
// Attempt #1
// myObject = extenderoony(myObject); // this fails, I think because the param reference overwrites the returned value
// Attempt 2
var a = extenderoony(myObject); // introduce the additional variable to receive the object ref
myObject = a; // And pass this reference on to the original. Phew, hacky.
$('#myObjectOut').html(JSON.stringify(myObject));
function extenderoony(obj){
var myDefaults = {
fontFamily : 'Tahoma',
fontSize: '15',
color : 'FF0000',
weight : 'bold',
decoration : 'underline'
}
obj = $.extend({}, obj, myDefaults); // << Changes the object reference of obj to a new object leaving the original object passed in as the parameter unchanged.
$('#obj').html(JSON.stringify(obj));
return obj; // have to send back the 'new' object reference cos we used that extend format !
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >Before the extend func</div>
<div id='myObjectIn'></div>
<hr>
<div >Inside the extend func</div>
<div id='obj'></div>
<hr>
<div >After the extend func</div>
<div id='myObjectOut'></div>
将选项扩展为默认值会导致myDefaults采用您显式指定的值。然后将myDefaults扩展为选项会使您更新传入的原始对象,而不是将其分配给全新的对象。
var myObject = {
fontFamily : 'Tahoma',
fontSize: '12',
color : '000000'
};
function extend ( options ) {
let myDefaults = {
fontFamily : 'Tahoma',
fontSize: '15',
color : 'FF0000',
weight : 'bold',
decoration : 'underline'
}
let temp = $.extend( myDefaults, options );
$.extend( options, myDefaults );
}
extend( myObject );
let expectedObject = {
fontFamily : 'Tahoma'
, fontSize: '12'
, color : '000000'
, weight : 'bold'
, decoration : 'underline'
};
Object.keys( expectedObject ).forEach( key => {
console.log( `Does ${key} match expected value?`, myObject[ key ] === expectedObject[ key ] );
} );
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
如果要跳过双扩展名,可以自己复制密钥。
var myObject = {
fontFamily : 'Tahoma',
fontSize: '12',
color : '000000'
};
function extend ( options ) {
let myDefaults = {
fontFamily : 'Tahoma',
fontSize: '15',
color : 'FF0000',
weight : 'bold',
decoration : 'underline'
}
Object.keys( myDefaults ).forEach( key => {
if ( options[ key ] === undefined ) options[ key ] = myDefaults[ key ];
} );
}
extend( myObject );
let expectedObject = {
fontFamily : 'Tahoma'
, fontSize: '12'
, color : '000000'
, weight : 'bold'
, decoration : 'underline'
};
Object.keys( expectedObject ).forEach( key => {
console.log( `Does ${key} match expected value?`, myObject[ key ] === expectedObject[ key ] );
} );
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>