首页 > 编程语言 >深入学习jquery源码之jQuery的构造函数与实例化

深入学习jquery源码之jQuery的构造函数与实例化

时间:2023-02-23 22:05:02浏览次数:40  
标签:jquery jQuery return function selector 源码 context prototype 构造函数


深入学习jquery源码之jQuery的构造函数与实例化

创建jQuery对象的整个流程如下:

1、调用$()方法;

2、调用jQuery.prototype.init()构造函数;

3、根据选择器不同返回不同的jQuery对象;

4、不同jQuery对象中公用的方法写在jQuery.prototype中;

5、将jQuery.prototype传递给jQuery.prototype.init.prototype,这样新创建的对象才可以访问公用方法;

 

创建jquery对象的四个步骤

第一步:创建jquery构造函数,并且实例化jQuery.fn.init(jquery的构造函数)。因为实例化的不是jQuery对象所以这上面不会挂载jQuery的方法,同时通过原型链也访问不到,jQuery使用了无new构造:将init()构造函数的定义放在了jQuery.prototype里面

jQuery = function (selector, context) {
// The jQuery object is actually just the init constructor 'enhanced'
// Need init if jQuery is called (just allow error to be thrown if not included)
return new jQuery.fn.init(selector, context);
}

 

在jQuery中,$是jQuery的别名,执行“$()”就是执行“jQuery()”,执行“$()”返回的是一个jQuery对象

var
// Map over jQuery in case of overwrite
_jQuery = window.jQuery,

// Map over the $ in case of overwrite
_$ = window.$;

jQuery.noConflict = function (deep) {
if (window.$ === jQuery) {
window.$ = _$;
}

if (deep && window.jQuery === jQuery) {
window.jQuery = _jQuery;
}

return jQuery;
};

// Expose jQuery and $ identifiers, even in
// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
if (typeof noGlobal === strundefined) {
window.jQuery = window.$ = jQuery;
}
return jQuery;

 

第二步:此方法则是用来扩展jQuery的实例方法,也就是说jQuery类的实例对象可以调用此函数

$.fn.extend({

theAlert:function(){

alert("自定义的函数");

}

})

$("thediv").theAlert()

jQuery.fn指向jQuery.prototype,jQuery.fn执行jQuery的原型对象。我们可以通过实例化的静态方法也就是我们的工具方法挂载在jQuery上,也可以获得jQuery.prototype上的属性。这样我们调用的时候不需要去实例化,而是可以直接去调用,将对象的方法挂载到jQuery.prototype上,我们系需要实例化之后才能够使用,针对的this的操作。

jQuery.fn = jQuery.prototype = {
// The current version of jQuery being used
jquery: version,

constructor: jQuery,

// Start with an empty selector
selector: "",

// The default length of a jQuery object is 0
length: 0,

toArray: function () {
return slice.call(this);
},

// Get the Nth element in the matched element set OR
// Get the whole matched element set as a clean array
get: function (num) {
return num != null ?

// Return just the one element from the set
(num < 0 ? this[num + this.length] : this[num]) :

// Return all the elements in a clean array
slice.call(this);
},

// Take an array of elements and push it onto the stack
// (returning the new matched element set)
pushStack: function (elems) {

// Build a new jQuery matched element set
var ret = jQuery.merge(this.constructor(), elems);

// Add the old object onto the stack (as a reference)
ret.prevObject = this;
ret.context = this.context;

// Return the newly-formed element set
return ret;
},

// Execute a callback for every element in the matched set.
// (You can seed the arguments with an array of args, but this is
// only used internally.)
each: function (callback, args) {
return jQuery.each(this, callback, args);
},

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

slice: function () {
return this.pushStack(slice.apply(this, arguments));
},

first: function () {
return this.eq(0);
},

last: function () {
return this.eq(-1);
},

eq: function (i) {
var len = this.length,
j = +i + (i < 0 ? len : 0);
return this.pushStack(j >= 0 && j < len ? [this[j]] : []);
},

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

// For internal use only.
// Behaves like an Array's method, not like a jQuery method.
push: push,
sort: deletedIds.sort,
splice: deletedIds.splice
};

 

第三步:jQuery.fn.extend(object)为jQuery对象添加方法,此方法是用来扩展jQuery类,它所方法是全局性,直接用jQuery类即可引用

$.extend({minValue:function(a,b){return a<b?a:b;}})

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

// Handle a deep copy situation
if (typeof target === "boolean") {
deep = target;

// skip the boolean and the target
target = arguments[i] || {};
i++;
}

// 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 passed
if (i === length) {
target = this;
i--;
}

for (; i < length; i++) {
// Only deal with non-null/undefined values
if ((options = arguments[i]) != null) {
// Extend the base object
for (name in options) {
src = target[name];
copy = options[name];

// Prevent never-ending loop
if (target === copy) {
continue;
}

// Recurse if we're merging plain objects or arrays
if (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 them
target[name] = jQuery.extend(deep, clone, copy);

// Don't bring in undefined values
} else if (copy !== undefined) {
target[name] = copy;
}
}
}
}

// Return the modified object
return target;
};

$.each方法的实现

$.each(obj,function(j,k){})

jQuery.extend({
// args is for internal usage only
each: function (obj, callback, args) {
var value,
i = 0,
length = obj.length,
isArray = isArraylike(obj);

if (args) {
if (isArray) {
for (; i < length; i++) {
value = callback.apply(obj[i], args);

if (value === false) {
break;
}
}
} else {
for (i in obj) {
value = callback.apply(obj[i], args);

if (value === false) {
break;
}
}
}

// A special, fast, case for the most common use of each
} else {
if (isArray) {
for (; i < length; i++) {
value = callback.call(obj[i], i, obj[i]);

if (value === false) {
break;
}
}
} else {
for (i in obj) {
value = callback.call(obj[i], i, obj[i]);

if (value === false) {
break;
}
}
}
}

return obj;
}
});

 

第四步:定义jquery的init构造方法

// A central reference to the root jQuery(document)
var rootjQuery,

// Use the correct document accordingly with window argument (sandbox)
document = window.document,

// A simple way to check for HTML strings
// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
// Strict HTML recognition (#11290: must start with <)
rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,

init = jQuery.fn.init = function (selector, context) {
var match, elem;

// HANDLE: $(""), $(null), $(undefined), $(false)
if (!selector) {
return this;
}

// Handle HTML strings
if (typeof selector === "string") {
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 check
match = [null, selector, null];

} else {
match = rquickExpr.exec(selector);
}

// Match html or make sure no context is specified for #id
if (match && (match[1] || !context)) {

// HANDLE: $(html) -> $(array)
if (match[1]) {
context = context instanceof jQuery ? context[0] : context;

// scripts is true for back-compat
// Intentionally let the error be thrown if parseHTML is not present
jQuery.merge(this, jQuery.parseHTML(
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true
));

// HANDLE: $(html, props)
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
for (match in context) {
// Properties of context are called as methods if possible
if (jQuery.isFunction(this[match])) {
this[match](context[match]);

// ...and otherwise set as attributes
} else {
this.attr(match, context[match]);
}
}
}

return this;

// 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 #6963
if (elem && elem.parentNode) {
// Handle the case where IE and Opera return items
// by name instead of ID
if (elem.id !== match[2]) {
return rootjQuery.find(selector);
}

// Otherwise, we inject the element directly into the jQuery object
this.length = 1;
this[0] = elem;
}

this.context = document;
this.selector = selector;
return this;
}

// 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);
}

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

// HANDLE: $(function)
// Shortcut for document ready
} else if (jQuery.isFunction(selector)) {
return typeof rootjQuery.ready !== "undefined" ?
rootjQuery.ready(selector) :
// Execute immediately if ready is not present
selector(jQuery);
}

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

return jQuery.makeArray(selector, this);
};


//init()构造函数最后返回了这个新对象的引用,并用jQuery的原型覆盖了init()的原型。等价于jQuery.prototype.init = function() {...return this;}
// Give the init function the jQuery prototype for later instantiation
init.prototype = jQuery.fn;

// Initialize central reference
rootjQuery = jQuery(document);

    新创建的对象无法访问jQuery.prototype中的其他属性,解决方法是:将jQuery.prototype传递jQuery.prototype.init.prototype:
    只有jQuery.fn.init的原型指向jQuery.fn(jQuery.prototype),这样我们在使用的时候就能够通过实例化的对象访问到挂载在jQuery.fn上的属性。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

标签:jquery,jQuery,return,function,selector,源码,context,prototype,构造函数
From: https://blog.51cto.com/u_11837698/6081934

相关文章

  • 深入学习jquery源码之queue()与dequeue()
    深入学习jquery源码之queue()与dequeue()queue(element,[queueName])概述显示或操作在匹配元素上执行的函数队列参数element,[queueName] Element,Stringelement:检查附加......
  • 深入学习jquery源码之序列化表单
    深入学习jquery源码之序列化表单serialize()概述序列表表格内容为字符串。序列表表格内容为字符串,用于Ajax请求。<pid="results"><b>Results:</b></p><form><select......
  • 深入学习jquery源码之jQuery的核心参数
    深入学习jquery源码之jQuery的核心参数jQuery([selector,[context]])概述这个函数接收一个包含CSS选择器的字符串,然后用这个字符串去匹配一组元素。jQuery的核心功能都是......
  • 深入学习jquery源码之is()与not()
    深入学习jquery源码之is()与not()is(expr|obj|ele|fn)概述根据选择器、DOM元素或jQuery对象来检测匹配元素集合,如果其中至少有一个元素符合这个给定的表达式就返回true。......
  • 深入学习jquery源码之arguments和callee
    深入学习jquery源码之argumentsjs中的函数其实是对象,函数名是对Function对象的引用,arguments这个对象不能显式创建,arguments对象只有函数开始时才可用。每创建一个函数,该......
  • 深入学习jquery源码之filter()与find()
    深入学习jquery源码之filter()与find()filter(expr|obj|ele|fn)概述筛选出与指定表达式匹配的元素集合。这个方法用于缩小匹配的范围。用逗号分隔多个表达式参数expr Strin......
  • 深入学习jquery源码之prop()与removeProp()
    深入学习jquery源码之prop()与removeProp()prop(name|properties|key,value|fn)概述获取在匹配的元素集中的第一个元素的属性值。随着一些内置属性的DOM元素或window对象,如......
  • 深入学习jquery源码之addClass()和toggleClass()与hasClass()
    深入学习jquery源码之addClass()和toggleClass()与hasClass()addClass(class|fn)概述为每个匹配的元素添加指定的类名。参数class String一个或多个要添加到元素中的CSS类......
  • 深入学习jquery源码之siblings()和children()与contents()
    深入学习jquery源码之siblings()和children()与contents()siblings([expr])概述取得一个包含匹配的元素集合中每一个元素的所有唯一同辈元素的元素集合。可以用可选的表达式......
  • 深入学习jquery源码之jQuery中高质量的代码
    深入学习jquery源码之jQuery中高质量的代码1、this指向的问题 functionStudent(name,age,grade,school){Person.apply(this,arguments);}他就具备了Pe......