jQuery logger插件 [英] jQuery logger plugin
问题描述
我正在开发一个jQuery插件,该插件可让您记录任何javascript类或对象. 这个想法是要覆盖对象内部的每个函数或函数的原型.
(function($)
{
"use strict";
$.log = function(object, logger)
{
if (!$.isFunction(logger))
{
logger = function(name, args)
{
console.log(name + "(" + $.makeArray(args).join(", ") + ")");
};
}
var s = $.isFunction(object) ? object.prototype : object;
for (name in s)
{
var fn = s[name];
if ($.isFunction(fn))
{
s[name] = (function(name, fn)
{
return function()
{
logger(name, arguments);
return fn.apply(this, arguments);
};
})(name, fn);
}
}
};
})(jQuery);
这似乎适用于记录单个插件.例如,$.log($.ui.tabs);
将所有函数调用记录在选项卡原型内.
但是当我想记录所有jQuery $.log($);
时,这给了我一些参考错误.
我不知道为什么会出现此错误.我觉得这与this
或要传递的参数有关,但我不确定.
现在我想一想,也可能是由于重写的函数总是返回而引起的.
我创建了一个小提琴来演示该问题: http://jsfiddle.net/Sj6xN/4/
这是我最终得到的代码,到目前为止运行良好:
(function($)
{
"use strict";
var Logger = function(options)
{
this.options = $.extend(this.defaults, options);
};
Logger.prototype = {
defaults:
{
inherited: false,
deep: false,
logWriter: function(name, args)
{
console.log("CALL: " + name + "(" + $.makeArray(args).join(", ") + ")");
}
},
augment: function(object)
{
var self = this;
// Make sure this object is not already augmented
if (object.__isAugmented__)
{
return;
}
// Set 'isAugmented' to prevent recursion
object.__isAugmented__ = true;
// Loop through the object
for (var name in object)
{
var originalFunction = object[name];
// If it's a function and the function is not inherited or 'inherited' is enabled augment it
if ($.isFunction(originalFunction) && (object.hasOwnProperty(name) || self.options.inherited))
{
// Wrap in self executing function so references to 'name' and 'orginalFunction' are maintained
object[name] = (function(name, originalFunction)
{
// If the function has a prototype and 'deep' is enabled augment that as well
if (self.options.deep && originalFunction.prototype)
{
self.augment(originalFunction.prototype);
}
var augmentedFunction = function()
{
// Execute log writer
self.options.logWriter(name, arguments);
// Call original function
return originalFunction.apply(this, arguments);
};
// Inherit prototype of original function
augmentedFunction.prototype = originalFunction.prototype;
// Return the augmented function
return augmentedFunction;
})(name, originalFunction);
}
// If it's a plain object and 'deep' is enabled augment that as well
else if (self.options.deep && $.isPlainObject(originalFunction))
{
self.augment(originalFunction);
}
}
}
};
$.log = function(object, options)
{
var logger = new Logger(options);
// If the object is a function use it's prototype, otherwise assume a plain object
object = $.isFunction(object) ? object.prototype : object;
// Augment
logger.augment(object);
};
})(jQuery);
可以这样使用:
$.log(<object or function> [,
{
inherited: <bool>,
deep: <bool>,
logWriter: <function(name, args)>
}]);
仔细检查该错误.
Uncaught ReferenceError: name is not defined
您尚未定义名称,并且由于您处于严格模式,因此您不能在没有定义的情况下使用变量(通常,如果您这样做,它将是全局变量,但不能在严格模式下使用).因此,如果您在var name
之前编写它,就不会再出现此错误.
尽管没有制表符方法还有另一个错误.另一个错误是说tabs
不是对象的方法,这是因为当您包装函数时,您没有继承原型,因此当用new调用该函数时,它没有原型函数(
这是固定代码: http://jsfiddle.net/Sj6xN/8/ >
I'm working on a jQuery plugin that allows you to log any javascript class or object. The idea is to override each function inside the object, or prototype of a function.
(function($)
{
"use strict";
$.log = function(object, logger)
{
if (!$.isFunction(logger))
{
logger = function(name, args)
{
console.log(name + "(" + $.makeArray(args).join(", ") + ")");
};
}
var s = $.isFunction(object) ? object.prototype : object;
for (name in s)
{
var fn = s[name];
if ($.isFunction(fn))
{
s[name] = (function(name, fn)
{
return function()
{
logger(name, arguments);
return fn.apply(this, arguments);
};
})(name, fn);
}
}
};
})(jQuery);
This seems to work for logging individual plugins. For example $.log($.ui.tabs);
logs all the function calls inside the tabs prototype.
But when I want to log all of jQuery $.log($);
it's giving me some reference error.
I can't figure out why I'm getting this error. I'm under the impression it has something to do with either this
or the arguments being passed, but I'm not sure.
Edit: Now I think about It some more it might also be caused because the overridden function always returns.
I created a fiddle to demo the problem: http://jsfiddle.net/Sj6xN/4/
EDIT:
This is the code i ended up with, so far working perfectly:
(function($)
{
"use strict";
var Logger = function(options)
{
this.options = $.extend(this.defaults, options);
};
Logger.prototype = {
defaults:
{
inherited: false,
deep: false,
logWriter: function(name, args)
{
console.log("CALL: " + name + "(" + $.makeArray(args).join(", ") + ")");
}
},
augment: function(object)
{
var self = this;
// Make sure this object is not already augmented
if (object.__isAugmented__)
{
return;
}
// Set 'isAugmented' to prevent recursion
object.__isAugmented__ = true;
// Loop through the object
for (var name in object)
{
var originalFunction = object[name];
// If it's a function and the function is not inherited or 'inherited' is enabled augment it
if ($.isFunction(originalFunction) && (object.hasOwnProperty(name) || self.options.inherited))
{
// Wrap in self executing function so references to 'name' and 'orginalFunction' are maintained
object[name] = (function(name, originalFunction)
{
// If the function has a prototype and 'deep' is enabled augment that as well
if (self.options.deep && originalFunction.prototype)
{
self.augment(originalFunction.prototype);
}
var augmentedFunction = function()
{
// Execute log writer
self.options.logWriter(name, arguments);
// Call original function
return originalFunction.apply(this, arguments);
};
// Inherit prototype of original function
augmentedFunction.prototype = originalFunction.prototype;
// Return the augmented function
return augmentedFunction;
})(name, originalFunction);
}
// If it's a plain object and 'deep' is enabled augment that as well
else if (self.options.deep && $.isPlainObject(originalFunction))
{
self.augment(originalFunction);
}
}
}
};
$.log = function(object, options)
{
var logger = new Logger(options);
// If the object is a function use it's prototype, otherwise assume a plain object
object = $.isFunction(object) ? object.prototype : object;
// Augment
logger.augment(object);
};
})(jQuery);
Can be used like this:
$.log(<object or function> [,
{
inherited: <bool>,
deep: <bool>,
logWriter: <function(name, args)>
}]);
Well look closely to the error.
Uncaught ReferenceError: name is not defined
Means you haven't defined name and since you are in strict mode, you can't use a variable without defining it(normally if you do it, it'll be a global variable, but not in strict mode). So if you write a var name
before it you won't get this error anymore.
Though there is another error for not having tab method. The other error says tabs
is not a method of the object which is because when you wrap the function, you didn't inherit the prototype, so when the function is called with new, it doesn't have prototype functions(tabs
is one of them).
Here's the fixed code : http://jsfiddle.net/Sj6xN/8/
这篇关于jQuery logger插件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!