jQuery 如何表现得像一个对象和一个函数?

IT技术 javascript jquery
2021-03-01 01:04:11

jQuery或者$似乎是一个函数:

typeof $; // "function"

它的作用就像一个:

$('div').removeClass(); // $ constructs a new object with some methods like removeClass

但是当我删除函数括号时,它的行为就像一个对象:

$.each(/* parameters */); // $ is an object with some methods like each

我想知道这是怎么可能的,以及如何将这种行为实现到我自己的函数中。

3个回答

函数也是对象,因此$.each可以以与对象类似的方式定义。

JavaScript 是一种原型语言。对于 jQuery,这意味着 的每个实例都$jQuery.prototype. 见注释

一个非常粗略的演示,以实现类似的行为:

(function() { // Closure to not leak local variables to the global scope
    function f(a, b) {
        //Do something
    }
    // Prototype. All properties of f.prototype are inherited by instances of f.
    // An instance of f can be obtained by:    new f, new f(), Object.create(f)
    f.prototype.removeClass = function(a) {
        return a;
    };
    function $(a, b) {
        return new f(a, b); // <--- "new f" !  
    } 
    $.each = function(a) {
        alert(a);             
    };
    window.$ = $; // Publish public methods
})();

//Tests (these do not represent jQuery methods):
$.each("Foo");                   // Alerts "Foo" (alert defined at $.each)
alert($().removeClass('Blabla'));// Alerts "Blabla"

笔记

jQuery 的 root 方法定义如下(仅显示相关部分):

(function(win) {
    var jQuery = function (selector, context) {
        return new jQuery.fn.init(selector, context, rootjQuery);
    };
    //$.fn = jQuery.fn is a shorthand for defining "jQuery plugins".
    jQuery.fn = jQuery.prototype = {
        constructor: jQuery,
        init: function( /* ..parameters.. */ ) { 
            //.... sets default properties...
        }
        //....other methods, such as size, get, etc...
        //.... other properties, such as selector, length, etc...
    };
    jQuery.fn.removeClass = function() { // (Actually via jQuery.fn.extend)
        // ... method logic...
    };  //...lots of other stuff...

    win.$ = win.jQuery = jQuery; //Publish method
})(window);

prototype方法的优点是非常容易链接方法和属性。例如:

$("body").find("div:first").addClass("foo");

实现此功能的方法可能是:

$.fn.find = function(selector) {
    ...
    return $(...);
};

如果您对 jQuery 的实际实现感兴趣,请查看带注释的源代码:

@JonathanLonowski 谢谢,这很整洁!我明白了,new构造原型需要关键字。我怎样才能让它像 jQuery 一样可选?
2021-04-24 01:04:11
@dotweb 它的诀窍是测试是否this instanceof ConstructorConstructor. 而且,如果不是,return new Constructor(arg1, arg2);. 您可以在他的博客上找到 John Resig 对此的总结您还可以在JS Perf上找到许多与性能相关的变体
2021-04-27 01:04:11
这对我来说只是警报 4,而不是 3!
2021-05-05 01:04:11
@dotweb 为我不完整的答案道歉,我不得不很快去。我刚刚完成了我的回答。
2021-05-09 01:04:11
@dotweb 尝试使用第二行作为alert(new $().removeClass());. jQuery 允许new关键字是可选的,但您需要在本演示中使用它。
2021-05-18 01:04:11

所有功能都以这种方式工作。

function fn() {
    alert("hi mom");
}

fn.foo = "bar";
在这种情况下,$("element")返回一个具有fn().
2021-04-25 01:04:11
但是它如何调用像 $("element").fn() 这样的函数。+1
2021-05-14 01:04:11

在 JavaScript 中,函数是一种对象。具体来说,函数是从 Object 派生的 Function 对象的实例。jQuery 利用这一事实并从 jQuery 函数对象中挂起一些“静态”方法。

jQuery 的创建者 John Resig 在http://ejohn.org/apps/learn/上有一个关于这个主题的很好的教程这可能会给你一些关于如何在你自己的代码中利用 JavaScript 的这个特性的想法。