为什么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;
},
我的问题是为什么所有方法都不是一个单独的对象的一部分,它成为自我对象的原型?
答案 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的注意事项,但这里有一些假设:
在我看来,他们不希望公开访问回调对象内部使用的所有内容。
使用新的。我没有看到jQuery要求客户端使用new
初始化API提供的对象。
新的可以通过以下方式避免:
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
的原型中查看。