jQuery源码分析-03构造jQuery对象-工具函数这篇文章对jQuery中扩展的一些工具函数做了下简要分析
关于isPlainObject函数,isPlainObject分析与重构这篇文章指出其存在bug,history,location,navigator,screen可以顺序通过 isPlainObject的检测返回true.
经本人测试,在ie8中确实存在bug返回true,但chrome中则返回的是false。
经过仔细分析发现bug原因,若obj = window.location, 在ie8中第二个if语句的第一个判断条件obj.constructor的值为undefined,而在chrome中为function Location() { [native code] }
其实第一个if语句的第二个判断条件可以过滤掉window.location等对象jQuery.type()源码为:
type: function( obj ) { return obj == null ? String( obj ) : class2type[ toString.call(obj) ] || "object"; },
class2type是在前面定义的一个空对象:
// [[Class]] -> type pairs class2type = {};
因为class2type没有内容,因此通过class2type无法区别window.location与其他object,所以只要obj不为空,都返回“object”。
如果class2type = {"[object Location]": "location",........};则可过滤出location之类的对象
isPlainObject完整代码如下
function isPlainObject( obj ) { // Must be an Object. // Because of IE, we also have to check the presence of the constructor property. // Make sure that DOM nodes and window objects don't pass through, as well //首先排除掉obj为空、非object类型和window及节点类型 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { return false; } //前两个判断条件不用多说,第三个判断条件是在obj的原型中找isPrototypeOf这个方法, //而这个方法只会存在于Object的原型中,也就是说如果obj的原型中存在isPrototypeOf则obj //是Object的直接实例。当然除非人为的将obj的构造函数的prototype.constructor置为Object, //或者将构造函数的prototype置为{} try { // Not own constructor property must be Object if ( obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } } catch ( e ) { // IE8,9 Will throw exceptions on certain host objects #9897 return false; } // Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. //因为in操作符只能访问到可枚举类型,若obj原型中有可枚举类型属性则return false //保证了obj是Object.prototype未被修改过的Object的直接实例。 var key; for ( key in obj ) {} return key === undefined || hasOwn.call( obj, key ); }
浙公网安备 33010602011771号