为什么jQuery代码不使用原型方法?

时间:2013-01-11 14:23:34

标签: javascript jquery

为什么jquery代码(https://github.com/jquery/jquery/blob/master/src/callbacks.js)不使用原型进行方法?

我问这个是因为experts suggest出于性能原因而将原型用于方法(因为函数只创建一次)。

来自jquery代码的代码片段

self = {
            // Add a callback or a collection of callbacks to the list
            add: function() {
                if ( list ) {
                    // First, we save the current length
                    var start = list.length;
                    (function add( args ) {
                        jQuery.each( args, function( _, arg ) {
                            var type = jQuery.type( arg );
                            if ( type === "function" ) {
                                if ( !options.unique || !self.has( arg ) ) {
                                    list.push( arg );
                                }
                            } else if ( arg && arg.length && type !== "string" ) {
                                // Inspect recursively
                                add( arg );
                            }
                        });
                    })( arguments );
                    // Do we need to add the callbacks to the
                    // current firing batch?
                    if ( firing ) {
                        firingLength = list.length;
                    // With memory, if we're not firing then
                    // we should call right away
                    } else if ( memory ) {
                        firingStart = start;
                        fire( memory );
                    }
                }
                return this;
            },
            // Remove a callback from the list
            remove: function() {
                if ( list ) {
                    jQuery.each( arguments, function( _, arg ) {
                        var index;
                        while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
                            list.splice( index, 1 );
                            // Handle firing indexes
                            if ( firing ) {
                                if ( index <= firingLength ) {
                                    firingLength--;
                                }
                                if ( index <= firingIndex ) {
                                    firingIndex--;
                                }
                            }
                        }
                    });
                }
                return this;
            },

我的问题是为什么所有方法都不是一个单独的对象的一部分,它成为自我对象的原型?

2 个答案:

答案 0 :(得分:3)

在这里使用这些特定函数允许在闭包中嵌入特定变量(例如list),同时保持它们是私有的。

以标准方式使用基于原型的对象会使这些属性公开。

拇指规则在选择时可能是变量一致性的必要性。当直接变量变化可能使对象处于无效状态时,更具保护性似乎是恰当的。例如,减少列表长度可能会使索引无效。

答案 1 :(得分:1)

使用原型时,您只能访问对象的privileged/public成员。

从代码中可以看出,jQuery没有将任何选项设置为Callback对象的公共/特权成员,它们使用闭包来访问Callback实例中的选项。如果他们初始化原型中的方法,他们将无法访问选项对象。

这是另一个例子:

使用原型

function Callback(opt) {
    var options = opt;
}

Callback.prototype.execute = function () {
   console.log(typeof options);   //undefined
}

不使用原型

function Callback(opt) {
    var options = opt;
    this.execute = function () {
       console.log(typeof options);   //object
    }
}

我无法确定jQuery的注意事项,但这里有一些假设:

  1. 在我看来,他们不希望公开访问回调对象内部使用的所有内容。

  2. 使用新的。我没有看到jQuery要求客户端使用new初始化API提供的对象。

  3. 新的可以通过以下方式避免:

    function Callbacks() {
        if (this === window) {
            return new Callbacks();
        }
    }
    
    Callbacks.prototype.method = function () {
        //implementation
    }
    
    var c = Callbacks(); 
    

    但是性能开销很少:

    • 由于递归调用return new Callbacks(),这是一个开销。
    • 另一个是因为new的使用。在jsperf中,您可以看到对象文字通常比new快。
    • 最后一个来自原型链的遍历:

      如果我使用:c.method();首先JS解释器将查看c的属性以调用method。当然它不会在那里找到它所以它也必须在c的原型中查看。