Cause of the problem in the difference in implementation of the function isPlainObject
in these two versions of jQuery.
The current isPlainObject in 1.4 tests .nodeType because IE makes dom nodes look like objects. This has the side effect that $.isPlainObject({ nodeType: ... }); will return false when it should return true. (From jQuery Forum)
Use jQuery 1.11.2
var data = {
colors: {
id: 1,
color: "red",
nodeType: function () {},
}
};
function logPlain (value, log) {
value && value.color == "red" && $('#plain').text(log);
}
//from release of jQuery UI-1.12.1
$.widget.extend = function( target ) {
var widgetSlice = Array.prototype.slice;
var input = widgetSlice.call( arguments, 1 );
var inputIndex = 0;
var inputLength = input.length;
var key;
var value;
for ( ; inputIndex < inputLength; inputIndex++ ) {
for ( key in input[ inputIndex ] ) {
value = input[ inputIndex ][ key ];
if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
// Clone objects
if ( $.isPlainObject( value ) ) {
logPlain(value, 'true');
target[ key ] = $.isPlainObject( target[ key ] ) ?
$.widget.extend( {}, target[ key ], value ) :
// Don't extend strings, arrays, etc. with objects
$.widget.extend( {}, value );
// Copy everything else by reference
} else {
logPlain(value, 'false');
target[ key ] = value;
}
}
}
}
return target;
};
$(function() {
$.widget("custom.widget2", {
options: {
data: null
},
_create: function() {
var isDataEqual = this.options.data == data.colors;
$('#equal').text(isDataEqual ? "true" : "false");
},
});
$("#my-widget1").widget2({
data: data.colors
});
});
#equal, #plain {
background-color: rgba(0, 128, 0, 0.31);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<div>
<div id="my-widget1">Testing 'nodeType' in jQuery version-1.11.2</div>
<div>isPlainObject: <span id="plain"></div>
<div>isDataEqual: <span id="equal"></span></div>
</div>
Use jQuery 3.1.1:
var data = {
colors: {
id: 1,
color: "red",
nodeType: function () {},
}
};
function logPlain (value, log) {
value && value.color == "red" && $('#plain').text(log);
}
//from release of jQuery UI-1.12.1
$.widget.extend = function( target ) {
var widgetSlice = Array.prototype.slice;
var input = widgetSlice.call( arguments, 1 );
var inputIndex = 0;
var inputLength = input.length;
var key;
var value;
for ( ; inputIndex < inputLength; inputIndex++ ) {
for ( key in input[ inputIndex ] ) {
value = input[ inputIndex ][ key ];
if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
// Clone objects
if ( $.isPlainObject( value ) ) {
logPlain(value, 'true');
target[ key ] = $.isPlainObject( target[ key ] ) ?
$.widget.extend( {}, target[ key ], value ) :
// Don't extend strings, arrays, etc. with objects
$.widget.extend( {}, value );
// Copy everything else by reference
} else {
logPlain(value, 'false');
target[ key ] = value;
}
}
}
}
return target;
};
$(function() {
$.widget("custom.widget2", {
options: {
data: null
},
_create: function() {
var isDataEqual = this.options.data == data.colors;
$('#equal').text(isDataEqual ? "true" : "false");
},
});
$("#my-widget1").widget2({
data: data.colors
});
});
#equal, #plain {
background-color: rgba(0, 128, 0, 0.31);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<div>
<div id="my-widget1">Testing 'nodeType' in jQuery version-3.1.1</div>
<div>isPlainObject: <span id="plain"></div>
<div>isDataEqual: <span id="equal"></span></div>
</div>
Call stack when creating new jQuery UI widget:
- _createWidget(options)
- $.widget.extend({}, options)
- $.isPlainObject(options.colors)
If $.isPlainObject(options.colors) == true
then options.colors
is cloned into a new object options
(jQuery 3.1.1). isDataEqual
will be false.
Otherwise options.colors
is copied by reference to a new object options
(jQuery 1.11.0). isDataEqual
will be true.
Why? In jQuery 1.11.2 in the method $.isPlainObject
there is the following check:
if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
return false;
}
So if there is a property nodeType
in the object, the method $.isPlainObject
returns false
.