了解jQuery的内部工作方式



所以我试图了解jQuery是如何在内部工作的。jQuery公开了一个全局$变量,它可以像一样使用

$('.abc') // returns a list of DOM nodes having class abc
$.ajax() // used to perform AJAX requests

正如您所看到的,$是来自语句1的函数,而它是来自语句2的对象。现在我知道这是可能的,因为JavaScript中有function Objects,这意味着一个函数也是JavaScript中的Object,因此你可以给它附加方法。但我不确定这是如何在内部实现的?

我在看这篇博客文章,它解释了如何使用"构造函数模式"来模拟jQuery,但您将如何使用该模式在$上附加方法?或者jQuery使用了一些完全不同的模式?下面是jQuery的一个小实现。这个代码可以做$(selector),但我如何在其中添加$.method

// Mini jQuery implementation 
var $ = (function() {
var JQuery = function(selector) {
if (selector === "document") {
this.elements = [document];
} else if (selector === "window") {
this.elements = [window];
} else {
this.elements = document.querySelectorAll(selector);
}
return this;
};
JQuery.prototype.each = function(callback) {
this.elements.forEach(function(element) {
callback(element);
});
return this;
};
JQuery.prototype.addClass = function() {
if (arguments.length === 0) return this;
else {
this.each(element => {
element.classList.add(...arguments);
});
return this;
}
};
return function(selector) {
return new JQuery(selector);
};
})();
// Use our mini jQuery to turn background of matching Nodes green
$(".abc").addClass("highlight");
.abc {
background : red;
}
.abc.highlight {
background: green;
}
		<div class="abc">Node 1</div>
		<div class="abc">Node 2</div>

构造函数模式实际上并不能解决$.method的问题,如果你想实现$.method,你必须解决一点,这是一个基于你的例子的简单解决方案:

var $ = (function() {

var JQuery = function(selector) {
if (selector === "document") {
this.elements = [document];
} else if (selector === "window") {
this.elements = [window];
} else {
this.elements = document.querySelectorAll(selector);
}
return this;
};
JQuery.prototype.each = function(callback) {
this.elements.forEach(function(element) {
callback(element);
});
return this;
};
JQuery.prototype.addClass = function() {
if (arguments.length === 0) return this;
else {
this.each(element => {
element.classList.add(...arguments);
});
return this;
}
};
return function(selector) {

// A simple function for extending object properties/values to another object
$.extend = JQuery.prototype.extend = function(source) {
if (typeof arguments[0] !== 'object') return;
for (var prop in source) {
if (source.hasOwnProperty(prop)) {
this[prop] = source[prop];
}
}
};

// Extend all the JQuery prototype methods to the '$' object
$.extend(JQuery.prototype);

// Others extensions that's can only accessed via '$.method' and not '$('selector').method'
$.extend({
ajax: function() {},
noop: function() {},
});

return new JQuery(selector);
};
})();
// Use our mini jQuery to turn background of matching Nodes green
$("body").addClass("highlight");
$.addClass.call($('body'), 'selected');

jQuery不使用$jQuery对象的构造函数模式,如果你检查一下,你可以看到$jQuery只是这里定义的init函数jQuery.fn.init构造函数,所有初始化的jQuery对象$("body")方法都附加到jQuery.fn(jQuery.prototype的别名((这是这里的一个例子(,其他方法如ajaxnoopisReady直接附加到$对象(这里是ajax方法的示例(。这就是为什么我们可以使用$.method语法访问这些方法。

很抱歉我的英语不好,我希望这对你有意义。

第1版:对于任何对jQuery内部工作方式感兴趣并想了解更多关于jQuery核心的人,我创建了这个github repo来了解jQuery的工作方式,尤其是为此目的。谢谢

相关内容

最新更新