为什么 JavaScript 函数别名不起作用?

发布于 2024-08-29 11:57:17 字数 423 浏览 3 评论 0原文

我有一些 Firebug 控制台函数调用,我想在未启用 Firebug 时禁用它们,例如未定义控制台。这在 IE6 和 FF3 中工作正常,但在 Chrome 中不行:

var log;

if(console){
  log = console.log;
}else{
  log = function(){ return; }
}

我在 Chrome 中收到“未捕获的类型错误:非法调用”=/

我读到了有关该问题的信息 这里,你必须应用一个上下文,这对我来说有点新......而且我似乎不知道如何完成在所有浏览器中均位于上方...

I have some Firebug console function calls that I wanted to disable when Firebug wasn't enabled, e.g. console isn't defined. This works fine in IE6 and FF3, but not in Chrome:

var log;

if(console){
  log = console.log;
}else{
  log = function(){ return; }
}

I get an "Uncaught TypeError: Illegal Invocation" in Chrome =/

I read about the issue here, where you have to apply a context, which is kind of new to me... and I can't seem to figure how to accomplish the above in all browsers...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦在深巷 2024-09-05 11:57:17

是的,您应该保留上下文:

var log;

if (window.console && typeof console.log === "function"){
  // use apply to preserve context and invocations with multiple arguments
  log = function () { console.log.apply(console, arguments); };
} else {
  log = function(){ return; }
}

发生的情况是,当您调用函数时,上下文(this 值)被隐式设置,例如:

var obj = {
  method: function () { return this; }
};

obj.method() === obj; // true

在这种情况下,您正在调用一个函数被定义为对象的属性,当调用该函数时,this 值将设置为该对象。

现在,如您的示例所示,如果将该方法的引用复制到变量:

var method = obj.method;
method() === window; // global object

如您所见,this 值引用全局对象。

因此,为了避免这种隐式行为,您可以使用 < 显式设置上下文代码>调用应用< /code>函数。

Yes, you should persist the context :

var log;

if (window.console && typeof console.log === "function"){
  // use apply to preserve context and invocations with multiple arguments
  log = function () { console.log.apply(console, arguments); };
} else {
  log = function(){ return; }
}

What is happening is that the context (the this value), is implicitly set when you call a function, for example:

var obj = {
  method: function () { return this; }
};

obj.method() === obj; // true

In this case, you are calling a function that is defined as a property of an object, when the function is invoked, the this value is set to that object.

Now as in your example, if you copy a reference of that method to a variable:

var method = obj.method;
method() === window; // global object

As you can see, the this value refers to the global object.

So, to avoid this implicit behavior you can set the context explicitly, with the call or apply functions.

脸赞 2024-09-05 11:57:17

将函数(如 console.log)包装在函数中的问题是它会丢失其上下文,即它不会显示我们放入“log”快捷方式的文件的正确行号。

相反,我建议一些东西像这样:

 window.log = ((window.console && window.console.log) ?
              console.log.bind(console) : 
              function(){});

这适用于 firebug & chrome 开发工具,并且在没有可用控制台时不会抛出错误。并且 - 最重要的是 - 显示正确的文件和信息行号。

The problem with wrapping a function (like console.log) in a function is that it loses its context, i.e. it will not show the correct line number of the file that we've put our "log" shortcut in.

Instead I suggest something like this:

 window.log = ((window.console && window.console.log) ?
              console.log.bind(console) : 
              function(){});

This works with firebug & chrome dev tools and does not throw errors when no console is available. And - most importantly - shows the correct file & line number.

飘逸的'云 2024-09-05 11:57:17

这是行不通的:

log("hi");

虽然这行得通:

log.call(console, "hi");

很明显,您需要使用正确的上下文调用别名函数——正如您自己所提到的。

我认为你必须使用函数包装器(一个引用原始上下文的闭包)而不是别名...

更新

另请注意,如果你直接检查 console ,你可能会当变量不存在时出现运行时错误。您最好将其显式检查为 window.console。这是实现条件log包装器的一种方法:

var log = (function (console) {
    return console
        ? function () { console.log.apply(console, arguments); }
        : function () {}
})(window.console);

This doesn't work:

log("hi");

While this does:

log.call(console, "hi");

It is obvious that you need to call the aliased function with the correct context -- as you yourself have mentioned.

I think you'll have to use a function wrapper (a closure that has a reference to the original context) rather than an alias...

Update

Also note that if you check for console directly, you may get a run-time error when the variable doesn't exist. You're better off checking it explicitly as window.console. Here's one way to implement a conditional log wrapper:

var log = (function (console) {
    return console
        ? function () { console.log.apply(console, arguments); }
        : function () {}
})(window.console);
无声情话 2024-09-05 11:57:17

此解决方案修改了 CMS 的早期优秀答案,以与 IE8 一起使用。在执行此操作之前,您需要打开 IE8 控制台(按 F12)。 (如果您忘记了,则需要完全退出 IE8 并重新启动,因为即使控制台存在,IE8 随后也不会创建 console 对象。)

请注意,我们不设置上下文,这是最初的问题,但事实证明,IE8 不需要该上下文。 (好事,因为 IE8 也不提供 console.log 对象上的 apply 方法!)。

此代码适用于最新版本的 Chrome、FireFox 和 MSIE。 (它与MSIE6兼容并且不会抛出错误。)

if((typeof console !== "undefined") && ((typeof console.log) !== "undefined"))
{
  if ((typeof console.log.apply !== "undefined"))
  {
    log = function() { console.log.apply(console,arguments) };
  }
  else
  {
    log = console.log;
  }
}
else
{
  log = function() {};
  // alert("No debug console");
}

This solution modifies the earlier and excellent answer from CMS to work with IE8. You’ll need to open the IE8 console (press F12) before executing this. (If you forget, you’ll need to exit IE8 entirely and start again because even if the console exists, IE8 won’t subsequently create the console object.)

Note that we don’t set the context, which was the original problem but, as it turns out, IE8 doesn’t require that context. (Good thing, because IE8 also doesn’t provide the apply method on the console.log object!).

This code works with the latest versions of Chrome, FireFox, and MSIE. (It is compatible with MSIE6 and doesn’t throw an error.)

if((typeof console !== "undefined") && ((typeof console.log) !== "undefined"))
{
  if ((typeof console.log.apply !== "undefined"))
  {
    log = function() { console.log.apply(console,arguments) };
  }
  else
  {
    log = console.log;
  }
}
else
{
  log = function() {};
  // alert("No debug console");
}
╄→承喏 2024-09-05 11:57:17

我做了这个

var log;

log = function() {
  if ((window.console != null) && (window.console.log.apply != null)) {
    return console.log.apply(console, arguments);
  } else {
    return function() {};
  }
};

I did this

var log;

log = function() {
  if ((window.console != null) && (window.console.log.apply != null)) {
    return console.log.apply(console, arguments);
  } else {
    return function() {};
  }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文