Javascript 为什么在重写console.log时会出现“超过最大调用堆栈大小”?
这是密码Javascript 为什么在重写console.log时会出现“超过最大调用堆栈大小”?,javascript,Javascript,这是密码 function getMilli(){ return new Date().getTime().toString().substr(7,6); } console.log = function(p1, p2, p3, p4, p5, p6){ console.log(getMilli(), p1, p2, p3, p4, p5, p6); } 不知怎的,它确实出现了堆栈溢出错误,但我不明白为什么在这里。。至少我认为我不是在递归地迭代 …嗯,是的,我在做递归的事情。。
function getMilli(){
return new Date().getTime().toString().substr(7,6);
}
console.log = function(p1, p2, p3, p4, p5, p6){
console.log(getMilli(), p1, p2, p3, p4, p5, p6);
}
不知怎的,它确实出现了堆栈溢出错误,但我不明白为什么在这里。。至少我认为我不是在递归地迭代
…嗯,是的,我在做递归的事情。。。但我不知道怎么做。感谢您的回答和伟大的概念。您正在递归调用函数console.log。换句话说,您正在console.log中调用console.log
你可能想做的是:
(function(){
var clog = console.log.bind(console);
console.log = function(p1, p2, p3, p4, p5, p6){
clog(getMilli(), p1, p2, p3, p4, p5, p6);
}
})();
显然,您是从console.log中调用console.log的,因为当您将它重新分配给新函数时,它不会保留到旧函数的链接,为什么要这样做 您想做的是:
console.old_log = console.log;
console.log = function() {
var args = Array.prototype.slice.call(arguments);
args.unshift(getMilli());
console.old_log.apply(console, args)
}
作为对其他有效答案的改进: 避免污染全局范围或任何对象的属性以存储原始console.log。 避免必须指定任意数量的占位符参数,如p1、p2、p3等。 使用闭包存储原始console.log,并删除对任意参数声明的依赖:
console.log = function (log) {
return function () {
var args = Array.prototype.slice.call(arguments);
args.unshift(getMillis()); // Push millis as first argument
log.apply(console, args);
};
}(console.log);
看起来我也是无限递归!您从console.log一直调用console.log。因为您是从console.log中调用console.log?这里的是日志异常。。。日志中的日志中的日志…如果可以的话,请避免使用p1、p2、p3等。@AtesGoral:谢谢,是的,我只是为了快速演示而做的:ASDF比我快了28秒。将删除我的答案并编辑你的答案以包含绑定技巧,我发现这在大多数浏览器中都是必要的。虽然我知道这只是为了演示一种快速的方法,但如果你没有用一个名为clog的变量污染全局名称空间,那就更好了。这里肯定有很多事情要做,但这是实现这一目标的最佳方式!谢谢:只是一个问题:您之所以调用var args=Array.prototype.slice.callarguments;是因为要将非数组类型的参数转换为数组,以便可以对数组使用unshift方法?我是新手JavaScript@JanCarloViray没错。这是将参数转换为常规数组的常见模式。我想知道为什么不在没有[call]的情况下使用它?是因为它会覆盖Array.prototype.slice吗?因此,通过使用call,您可以防止它被覆盖?@JanCarloViray slice不是一个静态实用程序方法,而是一个实例方法,也就是说,您首先需要一个数组实例。但是,它也适用于任何类似数组的对象。在这里,我们通过调用Array.prototype.slice并将参数作为作用域对象来模拟arguments.slice。当不带参数调用slice时,它类似于使用slice0调用它,因此它基本上是数组的一个副本。我们正在制作一个常规数组的参数副本。感谢您的贡献,尽管可以通过@AtesGoral查看“答案”以获得更好的实现