JQuery 扩展在移动到函数中时显示为中断



>问题:如何在不创建新的对象引用的情况下"就地"扩展对象。

剧情简介:JQuery extend按照它在锡上所说的去做。

但是,如果使用返回新对象的jquery.extend版本,那么新对象就是一个新对象。一切都很好,但是如果我在一个函数中进行扩展,我将对要扩展的对象的引用传递到其中,则原始对象保持不变。一个不错的陷阱等待着粗心的人(我(。您知道对象是通过引用传递的 - 对吗?

示例代码:假设我有一个对象

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>

我的回答感觉很笨拙 - 我会在下面发布它。

将选项扩展到默认值会导致 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>

这是我的答案 - 与问题相同的基本片段代码,并

添加了注释。

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>

最新更新