当前位置: 首页 > 编程日记 > 正文

jquery 1.7.2源码解析(二)构造jquery对象

构造jquery对象

jQuery对象是一个数组对象。

一)构造函数jQuery()

构造函数的7种用法:

1.jQuery(selector [, context ])

传入字符串参数:检查该字符串是选择器表达式还是HTML代码。如果是选择器表达式,则遍历文档查找匹配的DOM元素,

并创建一个包含这些DOM元素引用的jQuery对象。如果没有匹配的DOM,则创建一个length属性为0的空jQuery对象。

默认情况下对匹配元素的查找从根元素document开始,但也可以传入context参数限制查找范围。

如果选择器表达式是简单的'#id'且没有context参数,则调用document.getElementById()查找。

如果不是则调用jQuery的find()方法。

2.jQuery(html [, ownerDocument])、jQuery(html, props)

如果传入的参数是html代码,则尝试用html代码创建新的DOM元素,并创建包含这些DOM元素引用的jQuery对象。

如果html代码是单独的标签,使用document.createElement()创建DOM元素。如果是复杂的html代码,则使用innerHTML.

参数ownerDocument用于创建新DOM元素的文档对象,如果不传入默认为当前文档对象。

如果html代码是单独标签,第二个参数还可以是props,props是一个包含了属性、事件的普通对象,在调用了document.createElement()

方法创建了DOM元素后,参数props会被传给jQuery的attr()方法,由该方法设置新DOM的属性,事件。

$('<div/>', {"class": "test",text: "Click me!",click: function () {console.log("log");}
});

3.jQuery(element)、jQuery(elementArray)

如果传入一个DOM元素或者DOM元素数组,则封装DOM元素到jQuery对象种,并返回该jQuery对象。

$('#aInput').click(function () {$(this).val("value");
});

4.jQuery(object)

传入一个普通的js对象,则把该对象封装到jQuery对象中,并返回jQuery对象。

这个功能可以方便地在普通js对象上实现自定事件的绑定和触发。

var person = {name: 'Tony', gender: 'man'};
var $person = $(person);
$person.on('custom', function () {//do sth
});

5.jQuery(callback)

如果传入一个函数,则在document上绑定一个ready事件监听函数,当DOM结构加载完成时执行。

注意:ready事件要早于load事件发生。

6.jQuery(jQuery object)

创建一个副本并返回。

二)总体结构

jQuery对象模块总体结构:

(function ( window, undefined ) {//构造jQuery对象var jQuery = (function () {var jQuery = function (selector,context) {return new jQuery.fn.init(selector, context, rootjQuery);},//一堆局部变量声明//jQuery.fn成为jQuery.prototype的简写//覆盖jQuery原型的目的:方便继承,顺便也减少了创建每个jQuery实例所消耗的内存jQuery.fn = jQuery.prototype = {constructor: jQuery,init: function (selector, context, rootjQuery) {},//一堆原型属性和方法
        };//用jQuery的原型对象覆盖jQuery.fn.init.prototype的原型对象//使 new jQuery.fn.init()返回的实例也可以构造函数jQuery()的原型方法和属性
        jQuery.fn.init.prototype = jQuery.fn;
        jQuery.extend = jQuery.fn.extend = function () {};jQuery.extend({//一堆静态属性和方法
        });return jQuery;})();//省略其他模块代码window.jQuery = window.$ = jQuery;
})(window);

三)jQuery.fn.init(selector, context, rootjQuery)

1.12个分支

 2.源码分析

1)定义jQuery.fn.init(selector, context, rootjQuery):

jQuery.fn = jQuery.prototype = {constructor: jQuery,init: function( selector, context, rootjQuery ) {var match, elem, ret, doc;

构造函数接收三个参数:

selector:

context: 不传入,或者传入DOM元素,jQuery对象,普通js对象之一。

rootjQuery: 包含了document对象的jQuery对象。用于:

1.document.getElementById()查找失败

2.selector是选择器表达式且未指定context

3.selector是函数

2)参数selector可以转换为false

// Handle $(""), $(null), or $(undefined)if ( !selector ) {return this;}

3)参数selector是DOM元素

// Handle $(DOMElement)if ( selector.nodeType ) {this.context = this[0] = selector;this.length = 1;return this;}

4)参数selector是字符串'body'

// The body element only exists once, optimize finding itif ( selector === "body" && !context && document.body ) {this.context = document;this[0] = document.body;this.selector = selector;this.length = 1;return this;}

5)参数selector是其他字符串

先检测selector是HTML代码还是#id

        // Handle HTML stringsif ( typeof selector === "string" ) {// Are we dealing with HTML string or an ID?if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {// Assume that strings that start and end with <> are HTML and skip the regex checkmatch = [ null, selector, null ];} else {match = quickExpr.exec( selector );}

1.参数selector是单独标签

则调用document.createElement()创建DOM元素:

//如果是字符串if (typeof selector === 'string') {//如果是HTML字符串if (selector.charAt(0) === '<' && selector.charAt(length-1) === '>' && selector.length >= 3) {match = [null, selector, null];} else {match = quickExpr.exec(selector);}}if (match && (match[1] || !context)) {//HANDLE: $(html) -> $(array)if (match[1]) {context = context instanceof jQuery ? context[0] : context;doc = (context ? context.ownerDocument || context : document);//如果只传入了一个字符串,并且是个简单的html标签//就调用createElement,跳过剩余部分。ret = rsingleTag.exec( selector );if (ret) {//是否是纯粹对象if ( jQuery.isPlainObject( context ) ) {selector = [document.createElement(ret[1])];jQuery.fn.attr.call( selector, context, true );} else {selector = [document.createElement(ret[1])];}} else {ret = jQuery.buildFragment( match[1], [doc] );}

2.参数selector是复杂HTML代码

} else {ret = jQuery.buildFragment( [ match[1] ], [ doc ] );selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;}//将创建的DOM元素合并到当前jQuery对象中,并返回return jQuery.merge( this, selector );

3.参数selector是"#id",且未指定参数context

                // HANDLE: $("#id")} else {elem = document.getElementById( match[2] );// Check parentNode to catch when Blackberry 4.6 returns// nodes that are no longer in the document #6963if ( elem && elem.parentNode ) {// Handle the case where IE and Opera return items// by name instead of IDif ( elem.id !== match[2] ) {return rootjQuery.find( selector );}// Otherwise, we inject the element directly into the jQuery objectthis.length = 1;this[0] = elem;}this.context = document;this.selector = selector;return this;}

4.参数selector是选择器表达式

            // HANDLE: $(expr, $(...))} else if ( !context || context.jquery ) {return ( context || rootjQuery ).find( selector );// HANDLE: $(expr, context)// (which is just equivalent to: $(context).find(expr)} else {return this.constructor( context ).find( selector );}

5.参数selector是函数

// HANDLE: $(function)// Shortcut for document ready} else if ( jQuery.isFunction( selector ) ) {return rootjQuery.ready( selector );}

6.参数selector是jQuery对象

if ( selector.selector !== undefined ) {this.selector = selector.selector;this.context = selector.context;}

7.参数selector是其他任意值

如果selector是数组或者伪数组,则都添加到jQuery对象中,如果是JS

对象则作为第一个元素放入。该方法也可将6)中selector包含的全部元素引用复制到当前jQuery

return jQuery.makeArray( selector, this );

四)jQuery.buildFragment(args, nodes, scripts)

1.实现原理

该方法会先创建一个文档片段DocumentFragment,然后调用方法jQuery.clean(elems, context, fragment, scripts)

将HTML代码转换为HTML元素,并存储在创建的DocumentFragment中。

此外,如果HTML代码符合缓存条件,该方法还会把转换后的DOM缓存起来,第三次转换相同的HTML代码时直接从缓存中读取。

2.源码分析

1)参数:

args:数组,含有待转换为DOM元素的html代码

nodes:数组,含有文档对象、jQuery对象或DOM元素,用于修正创建文档片段DocumentFragment的文档对象。

scripts:数组,用于存放HTML代码中的script元素。

2)定义局部变量,修正文档对象doc

*
* fragment:指向创建的DocumentFragment
* cacheable: 是否符合缓存条件
* cacheresult:指向从缓存对象,jQuery.fragments提取到的文档片段,其中包含了缓存的DOM元素
* doc:创建文档片段的文档对象
* */
var fragment, cacheable, cacheresults, doc,first = args[ 0 ];// nodes may contain either an explicit document object,
// a jQuery collection or context object.
// If nodes[0] contains a valid object to assign to doc
if ( nodes && nodes[0] ) {doc = nodes[0].ownerDocument || nodes[0];
}// Ensure that an attr object doesn't incorrectly stand in as a document object
// Chrome and Firefox seem to allow this to occur and will throw exception
// Fixes #8950
if ( !doc.createDocumentFragment ) {doc = document;
}

3)其他操作

// Only cache "small" (1/2 KB) HTML strings that are associated with the main document
// Cloning options loses the selected state, so don't cache them
// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&first.charAt(0) === "<" && !rnocache.test( first ) &&(jQuery.support.checkClone || !rchecked.test( first )) &&(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {cacheable = true;cacheresults = jQuery.fragments[ first ];if ( cacheresults && cacheresults !== 1 ) {fragment = cacheresults;}
}
//转换HTML代码为DOM元素
if ( !fragment ) {fragment = doc.createDocumentFragment();jQuery.clean( args, doc, fragment, scripts );
}
//把转换后的DOM元素放入缓存对象jQuery.fragments中
if ( cacheable ) {jQuery.fragments[ first ] = cacheresults ? fragment : 1;
}
//返回文档片段和返回状态
return { fragment: fragment, cacheable: cacheable };
};jQuery.fragments = {};

五)jQuery.clean(elems, context, fragment, scripts)

1.实现原理

该方法负责把HTML代码转换为DOM元素,并提取其中的script元素。该方法会先创建一个临时

的div元素,并将其插入一个安全的文档片段(能正确渲染HTML5元素的文档片段)中,

然后把HTML代码赋值给div元素的innerHTML属性,最后解析div元素的子元素得到转换后的DOM。

2.源码分析

1)参数:

elems:数组,包含了待转换的html代码

context:文档对象

fragment:文档片段,存放转换后的DOM元素

scripts:数组,存放转换后的DOM元素中的script元素

2)修正文档对象

//ret用于存放转换后的DOM元素
var
checkScriptType, script, j,ret = [];context = context || document;// !context.createElement fails in IE with an error but returns typeof 'object' if ( typeof context.createElement === "undefined" ) {context = context.ownerDocument || context[0] && context[0].ownerDocument || document; }

3)遍历elems数组

//这里使用"!=",可以同时过滤undefined,null的情况,但不会过滤掉0
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {//如果elem是数字,则转换为字符串类型if (typeof elem === "number") {elem += "";}//如果elem是0,此时已经被转换为字符串“0”if (!elem) {continue;}

1.创建文本节点:

如果字符串不包含标签、字符代码和数字代码,则调用原生方法document.createTextNode()方法创建文本节点。

if ( !rhtml.test( elem ) ) {elem = context.createTextNode( elem );} else {
rhtml = /<|&#?\w+;/,

为什么不能包含标签、字符代码和数字代码?

因为document.createTextNode()方法对于传给它的字符串不会做转义解析。

而浏览器innerHTML机制可以。

2.修正自关闭标签

else {// Fix "XHTML"-style tags in all browserselem = elem.replace(rxhtmlTag, "<$1></$2>");
rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,

3.创建一个临时的div

// Trim whitespace, otherwise indexOf won't work as expectedvar tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(),
//从wrapMap提取对应的父标签,因为HTML语法要求这些标签必须包含在父标签中wrap
= wrapMap[ tag ] || wrapMap._default,
//包裹的深度,稍后会根据该变量剥去父元素depth
= wrap[0],div = context.createElement("div"),
rtagName = /<([\w:]+)/,
wrapMap = {option: [ 1, "<select multiple='multiple'>", "</select>" ],legend: [ 1, "<fieldset>", "</fieldset>" ],thead: [ 1, "<table>", "</table>" ],tr: [ 2, "<table><tbody>", "</tbody></table>" ],td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],area: [ 1, "<map>", "</map>" ],_default: [ 0, "", "" ]},

4.把临时div插入安全文档中去

                    // Append wrapper element to unknown element safe doc fragmentif ( context === document ) {// Use the fragment we've already created for this document
                        safeFragment.appendChild( div );} else {// Use a fragment created with the owner document
                        createSafeFragment( context ).appendChild( div );}
safeFragment = createSafeFragment( document );
function createSafeFragment( document ) {var list = nodeNames.split( "|" ),safeFrag = document.createDocumentFragment();if ( safeFrag.createElement ) {while ( list.length ) {safeFrag.createElement(list.pop());}}return safeFrag;
}

5.转换html代码为DOM元素

// Go to html and back, then peel off extra wrappers
div.innerHTML = wrap[1] + elem + wrap[2];// Move to the right depth
while ( depth-- ) {div = div.lastChild;
}

6.移除IE6\7自动插入的空tbody元素

                    // Remove IE's autoinserted <tbody> from table fragmentsif ( !jQuery.support.tbody ) {// String was a <table>, *may* have spurious <tbody>var hasBody = rtbody.test(elem),tbody = tag === "table" && !hasBody ?div.firstChild && div.firstChild.childNodes :// String was a bare <thead> or <tfoot>wrap[1] === "<table>" && !hasBody ?div.childNodes :[];for ( j = tbody.length - 1; j >= 0 ; --j ) {if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {tbody[ j ].parentNode.removeChild( tbody[ j ] );}}}

7)插入IE6\7\8自动删除的前导空白

// IE completely kills leading whitespace when innerHTML is usedif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );}

8)取到转换后的DOM元素集合

elem = div.childNodes;

9)修正IE7、8中复选框和单选框选中问题

10)合并转换后的DOM元素

if ( elem.nodeType ) {ret.push( elem );} else {ret = jQuery.merge( ret, elem );}

4)传入了fragment的情况

if ( fragment ) {checkScriptType = function( elem ) {return !elem.type || rscriptType.test( elem.type );};for ( i = 0; ret[i]; i++ ) {script = ret[i];if ( scripts && jQuery.nodeName( script, "script" ) && (!script.type || rscriptType.test( script.type )) ) {scripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );} else {if ( script.nodeType === 1 ) {var jsTags = jQuery.grep( script.getElementsByTagName( "script" ), checkScriptType );ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );}fragment.appendChild( script );}}}return ret;

六)jQuery.extend()、jQuery.fn.extend()

1.如何使用

用于合并两个或者多个对象的属性到第一个对象,语法:

jQuery.extend([deep], target, object1[, objectN]);

jQuery.fn.extend([deep], target, object1[, objectN]);

deep:布尔值,是否进行递归合并,默认为不递归

target:目标对象

objectN:源对象,包含的待合并的属性

如果仅提供一个对象,参数target将被忽略,当前的jQuery或者jQuery.fn被当作目标对象

通过这种方式在jQuery或者jQuery.fn上添加新的属性或者方法。

2.源码分析

1)定义局部变量

jQuery.extend = jQuery.fn.extend = function() {var options, name, src, copy, copyIsArray, clone,target = arguments[0] || {},i = 1,length = arguments.length,deep = false;

options:指向某个源对象

name:指向某个源对象的某个属性名

src:某个目标对象的某个属性原始值

copy:某个源对象的某个属性值

copyIsArray:指示变量copy是否是数组

clone:深度复制时,原始值的修正值

target:指向目标对象

i:源对象的起始下标

length:表示参数的个数,用于修正变量target

deep:是否深度合并,默认为false

jQuery.extend = jQuery.fn.extend = function() {var options, name, src, copy, copyIsArray, clone,target = arguments[0] || {},i = 1,length = arguments.length,deep = false;// Handle a deep copy situationif ( typeof target === "boolean" ) {deep = target;target = arguments[1] || {};// skip the boolean and the targeti = 2;}// Handle case when target is a string or something (possible in deep copy)if ( typeof target !== "object" && !jQuery.isFunction(target) ) {target = {};}// extend jQuery itself if only one argument is passedif ( length === i ) {target = this;--i;}for ( ; i < length; i++ ) {// Only deal with non-null/undefined valuesif ( (options = arguments[ i ]) != null ) {// Extend the base objectfor ( name in options ) {src = target[ name ];copy = options[ name ];// Prevent never-ending loopif ( target === copy ) {continue;}// Recurse if we're merging plain objects or arraysif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {if ( copyIsArray ) {copyIsArray = false;clone = src && jQuery.isArray(src) ? src : [];} else {clone = src && jQuery.isPlainObject(src) ? src : {};}// Never move original objects, clone themtarget[ name ] = jQuery.extend( deep, clone, copy );// Don't bring in undefined values} else if ( copy !== undefined ) {target[ name ] = copy;}}}}// Return the modified objectreturn target;
};

七)原型属性和方法

1. .selector、.jQuery、.length、.size()

1)selector:用于记录jQuery查找和过滤DOM元素时的选择器表达式,可用于调试。

2)jQuery:表示jQuery的版本号

3)length:表示当前jQuery对象中元素的个数

4)方法size():功能上等价于length

    // Start with an empty selectorselector: "",// The current version of jQuery being usedjquery: "1.7.2",// The default length of a jQuery object is 0length: 0,// The number of elements contained in the matched element setsize: function() {return this.length;},

2..toArray()、.get([index])

1.toArray():将当前jQuery对象转换为真正的数组,转换后的数组包含了所有元素。

slice = Array.prototype.slice,
toArray: function() {return slice.call( this, 0 );},

2.get([index]):返回当前jQuery对象中指定位置的元素或包含了全部元素的数组(无参)。

    get: function( num ) {return num == null ?// Return a 'clean' arraythis.toArray() :// Return just the object( num < 0 ? this[ this.length + num ] : this[ num ] );},

3. .each( function(index, Elment) )、 jQuery.each( collection, callback( indexArray, valueOfValue ) )

1. .each( function(index, Elment) )

遍历当前jQuery对象,并在每个元素上执行回调函数。每当执行回调函数

函数执行时会传递当前循环次数作为参数,更重要的是回调函数在当前

上下文环境中触发,在回调函数中返回false可以终止遍历。

each: function( callback, args ) {return jQuery.each( this, callback, args );},

2.jQuery.each( collection, callback ( indexArray, valueOfValue ) )

通用的遍历方法,用于无缝地遍历对象和数组,对于数组和类数组通过下标

遍历,对于其他对象则通过属性名遍历。在遍历过程中如果回调函数返回false则结束遍历。

/* ** object:待遍历的对象或者数组* callback: 回调函数,会在数组的每个元素或者对象的每个属性上执行* args: 传递给回调函数的参数数组,可选,如果没有传入,则执行回调* 函数时传入两个参数(下标或属性名,元素或属性值),如果传入了参数* 则把该参数传递给回调函数。** */
each: function( object, callback, args ) {var name, i = 0,length = object.length,isObj = length === undefined || jQuery.isFunction( object );if ( args ) {if ( isObj ) {for ( name in object ) {if ( callback.apply( object[ name ], args ) === false ) {break;}}} else {for ( ; i < length; ) {if ( callback.apply( object[ i++ ], args ) === false ) {break;}}}// A special, fast, case for the most common use of each} else {if ( isObj ) {for ( name in object ) {if ( callback.call( object[ name ], name, object[ name ] ) === false ) {break;}}} else {for ( ; i < length; ) {if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {break;}}}}return object;
},

4. .map( callback(index, domElement) )、 jQuery.map( arrayOrObject, callback(value, indexOrKey) )

1) .map( callback(index, domElement) )

遍历当前jQuery对象,在每个元素上执行回调函数,并将回调函数的返回值放入一个新的jQuery对象中。

map: function( callback ) {return this.pushStack( jQuery.map(this, function( elem, i ) {return callback.call( elem, i, elem );}));},

2) jQuery.map( arrayOrObject, callback(value, indexOrKey) )

对数组的每个元素或者对象的每个属性调用一个回调函数,并将回调函数的返回值放入一个新的数组中。

执行回调函数时传入两个参数:数组元素或属性值,元素下标或属性名。关键字this指向全局对象window。

//参数arg仅限于jQuery内部使用
map: function( elems, callback, arg ) {var value, key, ret = [],i = 0,length = elems.length,// jquery objects are treated as arraysisArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;// Go through the array, translating each of the items to theirif ( isArray ) {for ( ; i < length; i++ ) {value = callback( elems[ i ], i, arg );if ( value != null ) {ret[ ret.length ] = value;}}// Go through every key on the object,} else {for ( key in elems ) {value = callback( elems[ key ], key, arg );if ( value != null ) {ret[ ret.length ] = value;}}}// Flatten any nested arraysreturn ret.concat.apply( [], ret );
},

5. .pushStack( elements, name, arguments )

创建一个新的空jQuery对象,然后把DOM对象元素集合放入对象中,并保留对当前jQuery对象的引用。

//elems: 放入新jQuery对象的元素数组
//name: 产生元素数组的jQuery方法名
//修正原型属性的.selector
pushStack: function( elems, name, selector ) {// Build a new jQuery matched element setvar ret = this.constructor();if ( jQuery.isArray( elems ) ) {push.apply( ret, elems );} else {jQuery.merge( ret, elems );}// Add the old object onto the stack (as a reference)ret.prevObject = this;ret.context = this.context;if ( name === "find" ) {ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;} else if ( name ) {ret.selector = this.selector + "." + name + "(" + selector + ")";}// Return the newly-formed element setreturn ret;
},

6.  .end()

end: function() {return this.prevObject || this.constructor(null);},

7. .eq(index)、 .first()、 .last()、 .slice(start[, end])

    eq: function( i ) {i = +i;return i === -1 ?this.slice( i ) :this.slice( i, i + 1 );},first: function() {return this.eq( 0 );},last: function() {return this.eq( -1 );},slice: function() {return this.pushStack( slice.apply( this, arguments ),"slice", slice.call(arguments).join(",") );},

八)静态属性和方法

1. jQuery.onConflit([removeAll])

用于释放jQuery对全局变量的控制权

// Map over jQuery in case of overwrite_jQuery = window.jQuery,// Map over the $ in case of overwrite_$ = window.$,

noConflict: function( deep ) {if ( window.$ === jQuery ) {window.$ = _$;}if ( deep && window.jQuery === jQuery ) {window.jQuery = _jQuery;}return jQuery;},

2.类型检测:jQuery.isFunction(obj)、 jQuery.isArray(obj)、jQuery.isWindow(obj)、

jQuery.isNumeric(value)、jQuery.type(obj)、jQuery.isPlainObject(object)、jQuery.isEmptyObject(object)

isFunction: function( obj ) {return jQuery.type(obj) === "function";
},isArray: Array.isArray || function( obj ) {return jQuery.type(obj) === "array";
},isWindow: function( obj ) {return obj != null && obj == obj.window;
},isNumeric: function( obj ) {return !isNaN( parseFloat(obj) ) && isFinite( obj );
},type: function( obj ) {return obj == null ?String( obj ) :class2type[ toString.call(obj) ] || "object";
},//是否是以{}或者new Object()创建的
isPlainObject: function( 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 wellif ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {return false;}try {// Not own constructor property must be Object//如果obj没有属性constructor,则说明该对象必然是通过对象字面量{}创建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 #9897return false;}// Own properties are enumerated firstly, so to speed up,// if last one is own, then all properties are own.//在for循环中会先枚举非继承属性,再枚举继承属性var key;for ( key in obj ) {}return key === undefined || hasOwn.call( obj, key );
},isEmptyObject: function( obj ) {for ( var name in obj ) {return false;}return true;
},

3.解析JSON和XML:jQuery.parseJSON(data)、 jQuery.parseXML(data)

1.jQuery.parseJSON(data)

    parseJSON: function( data ) {if ( typeof data !== "string" || !data ) {return null;}// Make sure leading/trailing whitespace is removed (IE can't handle it)data = jQuery.trim( data );// Attempt to parse using the native JSON parser firstif ( window.JSON && window.JSON.parse ) {return window.JSON.parse( data );}// Make sure the incoming data is actual JSON// Logic borrowed from http://json.org/json2.jsif ( rvalidchars.test( data.replace( rvalidescape, "@" ).replace( rvalidtokens, "]" ).replace( rvalidbraces, "")) ) {return ( new Function( "return " + data ) )();}jQuery.error( "Invalid JSON: " + data );},

2.jQuery.parseXML(data)

    parseXML: function( data ) {if ( typeof data !== "string" || !data ) {return null;}var xml, tmp;try {if ( window.DOMParser ) { // Standardtmp = new DOMParser();xml = tmp.parseFromString( data , "text/xml" );} else { // IExml = new ActiveXObject( "Microsoft.XMLDOM" );xml.async = "false";xml.loadXML( data );}} catch( e ) {xml = undefined;}if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {jQuery.error( "Invalid XML: " + data );}return xml;},

4.jQuery.globalEval( code )

用于在全局作用域中执行javascript代码

    globalEval: function( data ) {if ( data && rnotwhite.test( data ) ) {// We use execScript on Internet Explorer// We use an anonymous function so that context is window// rather than jQuery in Firefox( window.execScript || function( data ) {window[ "eval" ].call( window, data );} )( data );}},

5.jQuery.camelCase(string)

转换连字符形式的字符串为驼峰式

6.jQuery.nodeName(elem, name)

用于检查节点名称是否与指定值相等,检查时忽略大小写

nodeName: function( elem, name ) {return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();},

7. 数组操作方法

1.jQuery.makeArray(obj)

将类数组对象转换为真正的数组

// results is for internal usage onlymakeArray: function( array, results ) {var ret = results || [];if ( array != null ) {// The window, strings (and functions) also have 'length'// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930var type = jQuery.type( array );if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {push.call( ret, array );} else {jQuery.merge( ret, array );}}return ret;},

2. jQuery.inArray(value, array[, fromIndex])

在数组中查找指定的元素并返回其下标,未找到则返回-1

/*
* elem: 要查找的值
* array: 被遍历的数组
* i: 指定开始查找的位置
* */
inArray: function( elem, array, i ) {var len;if ( array ) {if ( indexOf ) {return indexOf.call( array, elem, i );}len = array.length;i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;for ( ; i < len; i++ ) {// Skip accessing in sparse arraysif ( i in array && array[ i ] === elem ) {return i;}}}return -1;
}

3. jQuery.merge(first, second)

用于合并两个数组的元素到第一个数组。

第一个参数也可以时类数组对象(即必须有整型属性length值)。

第二个参数可以是数组,类数组或者有连续整型属性的对象。

    merge: function( first, second ) {var i = first.length,j = 0;if ( typeof second.length === "number" ) {for ( var l = second.length; j < l; j++ ) {first[ i++ ] = second[ j ];}} else {while ( second[j] !== undefined ) {first[ i++ ] = second[ j++ ];}}first.length = i;return first;},

4.jQuery.grep(array, function(elemOfArray, indexInArray)[, invert])

用于查找数组中满足过滤函数的元素,原数组不受影响。如果invert没有传入,或者传入false.

元素只有在过滤函数返回true时,才会被保存在最终的结果中。如果传入true情况相反。

    grep: function( elems, callback, inv ) {var ret = [], retVal;inv = !!inv;// Go through the array, only saving the items// that pass the validator functionfor ( var i = 0, length = elems.length; i < length; i++ ) {retVal = !!callback( elems[ i ], i );if ( inv !== retVal ) {ret.push( elems[ i ] );}}return ret;},

8. jQuery.proxy()

    // Bind a function to a context, optionally partially applying any// arguments.proxy: function( fn, context ) {if ( typeof context === "string" ) {var tmp = fn[ context ];context = fn;fn = tmp;}// Quick check to determine if target is callable, in the spec// this throws a TypeError, but we will just return undefined.if ( !jQuery.isFunction( fn ) ) {return undefined;}// Simulated bindvar args = slice.call( arguments, 2 ),proxy = function() {return fn.apply( context, args.concat( slice.call( arguments ) ) );};// Set the guid of unique handler to the same of original handler, so it can be removedproxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;return proxy;},

9. jQuery.access()

为集合中的元素设置一个或者多个属性值,或者读取第一个元素的属性值。

转载于:https://www.cnblogs.com/Shadowplay/p/9773439.html

相关文章:

Map接口及其常用方法

Map集合基于键(key)和值(value)的映射&#xff0c;每个键只能映射一个值&#xff0c;也就是说key不可以重复&#xff08;当然喽&#xff0c;重复的话就按最后一个为准&#xff09;。键和值都可以是任何引用数据类型的值&#xff1b;且一对键值的存放是无序的。 Map常用的实现类…

C++计时函数

推荐使用chrono计时函数 #include<iostream> #include<vector> #include<algorithm> #include<chrono> using namespace std; class mycom { public:bool operator()(pair<int,int> p1,pair<int,int> p2){return p1.first < p2.first;…

最长递增子序列的两种解法

以LeetCode-300为例&#xff1a; O(n^2)解法&#xff1a; dp数组表示以i结尾的最长递增子序列的长度 class Solution { public:int lengthOfLIS(vector<int>& nums) {const int size nums.size();if (size 0) { return 0; } vector<int> dp(size, 1);int res…

【救援过程】升级openssl导致libcrypto.so.1.1动态库不可用

目录 一、故障重现 二、救援过程 一、故障重现 近日为了解决CVE-2021-3449: 拒绝服务漏洞、CVE-2021-3450: 证书校验漏洞&#xff0c;自己编译了openssl-1.1.1k。 亲测发现&#xff1a;只升级openssl的版本&#xff0c;动态库版本没有升级&#xff0c;系统可用。 升级openss…

C++类class

一、定义 构造函数&#xff1a;在定义一个类对象时会自动调用&#xff0c;可用于实现一些功能&#xff0c;比如new一个内存。 构造函数&#xff0c;没有返回值也不写void函数名称与类名相同构造函数可以有参数&#xff0c;因此可以发生重载程序在调用对象时候会自动调用构造&…

pandas学习之Series结构

#!/usr/bin/env python # -*- coding:utf-8 -*- """ 系列&#xff08;值的集合&#xff09; DataFrame数据包&#xff08;系列对象的集合&#xff09; panel&#xff08;数据文件对象的集合) 一个系列对象可以保存许多数据类型&#xff0c;包括 浮点数表示浮点数…

Java中的Map集合遍历总结(详尽版)

因为Map集合中的键值对排列无序&#xff0c;所以不能用传统的for循环来遍历&#xff0c;只能使用加强循环(for-each)和迭代器进行遍历。 让我们通过例子来了解Map集合的遍历&#xff1a; package gather; import java.util.HashMap; import java.util.Iterator; import java.…

Ansible01-Ansible基础和部署

目录 一、Ansible简介 二、安装部署Ansible 2.1、在控制节点安装ansible 2.2、对Linux和Unix受管节点要求 2.3、基于 Microsoft Windows 的受管主机 2.4、受管网络设备 三、Ansible配置文件 3.1、ansible.cfg配置文件推荐做法 3.2、ansible.cfg配置文件内容 四、Ansi…

C++/C文件读取

1、C文件操作 ofstream&#xff1a;写操作ifstream&#xff1a; 读操作fstream &#xff1a; 读写操作 打开方式解释ios::in为读文件而打开文件ios::out为写文件而打开文件ios::ate初始位置&#xff1a;文件尾ios::app追加方式写文件ios::trunc如果文件存在先删除&#xff0c…

HashSet中的add()方法( 二 )(详尽版)

本篇接着上一篇&#xff1a;&#xff08;详尽版&#xff09;HashSet中的add()方法( 一 )&#xff08;详尽版&#xff09; 有些东西上一篇说过了&#xff0c;这里就不再赘述了&#xff0c;具体说一下再次添加与第一次添加的区别&#xff1a; import java.util.HashSet;public …

20155321 实验四 Android程序设计

20155321 实验四 Android程序设计 安装Android studio成功 任务一&#xff1a;Android Stuidio的安装测试&#xff1a; 参考《Java和Android开发学习指南(第二版)(EPUBIT,Java for Android 2nd)》第二十四章&#xff1a; 安装 Android Stuidio完成Hello World, 要求修改res目录…

Ansible02-实施playbook

一、编写和运行playbook 1.1、编写playbook play 是针对清单中选定的主机运行的一组有序任务。playbook 是一个文本文件&#xff0c;其中包含由一个或多个按特定顺序运行的 play 组成的列表。 playbook 是以 YAML 格式编写的文本文件&#xff0c;通常使用扩展名 .yml 保存。…

linux下解压缩文件中文乱码问题的解决

在windows上压缩的文件&#xff0c;是以系统默认编码中文来压缩文件。由于zip文件中没有声明其编码&#xff0c;所以linux上的unzip一般以默认编码解压&#xff0c;中文文件名会出现乱码。 虽然2005年就有人把这报告为bug, 但是info-zip的官方网站没有把自动识别编码列入计划&a…

ROS知识点总结

1、ROS功能包的目录下不能有中文 2、 WorkSpace --- 自定义的工作空间|--- build:编译空间&#xff0c;用于存放CMake和catkin的缓存信息、配置信息和其他中间文件。|--- devel:开发空间&#xff0c;用于存放编译后生成的目标文件&#xff0c;包括头文件、动态&静态链接库…

Effective Java:对于全部对象都通用的方法

前言&#xff1a; 读这本书第1条规则的时候就感觉到这是一本非常好的书。可以把我们的Java功底提升一个档次&#xff0c;我还是比較推荐的。这里我主要就关于覆盖equals、hashCode和toString方法来做一个笔记总结。希望可以与君共勉。 概述&#xff1a; 这一章主要是说明一些对…

HashSet中的add()方法( 一 )(详尽版)

让我们用例子来理解add()方法的底层代码吧&#xff0c;Let’s go&#xff1a; import java.util.HashSet;public class Test {public static void main(String[] args) {HashSet<String> names new HashSet<String>();names.add("Jim");//向HashMap集合…

Ansible03-管理变量、加密、事实

目录 一、管理变量 1.1、变量的基本用法 1.2、使用已注册变量捕获命令输出 二、管理加密 2.1、ansible-vault常用场景 三、管理事实 3.1、事实基本用法 3.2、创建自定义事实 3.3、魔法变量hostvars、group_names、groups、inventory_hostname 一、管理变量 1.1、变量…

HashSet中的add()方法( 零 )(详尽版)

我们知道在使用HashSet集合时&#xff0c;也就是在用HashMap集合&#xff0c;这是因为HashSet的底层是HashMap&#xff0c; public HashSet() {map new HashMap<>(); }在详述HashSet中的add()方法之前&#xff0c;我们要知道HashMap中的hash&#xff0c;因为在add()的底…

layui上传图片接口

mvc中 前台调用接口 url&#xff1a;"../upload/uploadfiles/" 然后开始接口 代码&#xff1a; string a ""; try { HttpFileCollection file context.Request.Files;//获取选中的文件 for (int i 0; i < file.Count; i) { string cFileName Path.G…

shell与 .sh文件与 .bash文件

一、shell和bash shell是LInux系统下的解释器&#xff0c;类似于windows下的cmd。shell对用户输入到窗口中的命令行进行解释&#xff0c;输入到内核。 bash同样是Linux系统下的解释器&#xff0c;是bash的改进版。 二、.sh文件与.bash文件 .sh文件和.bash文件都是脚本文件&a…

php session存入redis

一、 安装phpredis扩展php连接redis需要安装phpredis扩展。下载地址&#xff1a;https://github.com/phpredis/phpredis/releases&#xff0c;选用相应版本。笔者用的是php5.6.29&#xff0c;下载了phpredis-3.0.0安装出了问题&#xff0c;于是换成phpredis-2.2.8&#xff0c;正…

Ansible04-任务控制

目录 一、循环 二、条件 三、handlers 四、失败的处理 一、循环 使用 loop 关键字对一组项目迭代任务&#xff0c;循环变量 item 保存每个迭代过程中使用的值。 [studentworkstation ansible]$ vim loop.yml --- - name: Test loophosts: devgather_facts: novars:num:- …

HashSet中的add()方法( 三 )(详尽版)

上接HashSet中的add()方法( 二 )&#xff08;详尽版&#xff09; &#xff0c;前两篇说的是泛型为String类的add()方法的具体执行过程&#xff0c;此后三篇说说泛型为自定义类的add()方法的具体执行过程&#xff1a; 首先让我们来自定义一个学生类&#xff1a; public class …

mono修改配置

当前mono安装目录为:/home/mono&#xff0c;安装成功后修改配置需进入这个路径&#xff1a; cd /home/mono 1.修改TcpBinaryFrameManager.cs文件 cd /home/mono/mono-2.10.8 vim mcs/class/System.ServiceModel/System.ServiceModel.Channels.NetTcp/TcpBinaryFrameManager.cs …

[Java in NetBeans] Lesson 01. Java Programming Basics

这个课程的参考视频在youtube。 主要学到的知识点有&#xff1a; Create new project, choose Java Application.one .jar file/ package(.jar name with the same as package), one package can contains mutiple .java files.Comment mutiple lines by using "/* */&quo…

ubuntu中常用指令

常用指令 清空命令行 CtrlL Conda 创建虚拟环境 conda create -n 虚拟环境名称 python3.7.10 查看虚拟环境列表 conda info --envs 激活虚拟环境 conda activate 虚拟环境名 退出虚拟环境 conda deactivate 虚拟环境名称 安装功能包 conda install 功能包名称 卸载功能包 con…

Ansible05-部署文件

目录 一、部署文件的常用模块 二、使用jinja2文件部署自定义文件 一、部署文件的常用模块 部署文件常用模块有 file 创建、删除文件或目录&#xff0c;修改selinux上下文。copy 复制文件到受控节点上&#xff0c;也可以直接在受控结点上创建文件。fetch 从受控结点获取文件…

HashSet中的add()方法( 四 )(详尽版)

上接 HashSet中的add()方法( 三 )&#xff08;详尽版&#xff09; &#xff0c;我们重写一下Student类中的hashCode()方法来看看是否还能不能添加重复的学号了&#xff0c; 在学生类中重写hashCode()方法&#xff1a; public class Student {private String id;public Studen…

Laravel框架中的event事件操作

有时候当我们单纯的看 Laravel 手册的时候会有一些疑惑&#xff0c;比如说系统服务下的授权和事件&#xff0c;这些功能服务的应用场景是什么&#xff0c;其实如果没有经历过一定的开发经验有这些疑惑是很正常的事情&#xff0c;但是当我们在工作中多加思考会发现有时候这些服务…

yolact_ros出坑记录

教程&#xff1a;https://github.com/Eruvae/yolact_ros 下载通信中的话题msg 创建虚拟环境 conda create -n yolact python3.7.10 conda activate yolact 配置yolact环境 https://github.com/dbolya/yolact 运行效果如下所示&#xff1a; 在虚拟环境中安装需要的包 conda …