JavaScript: 重写 alert()

212

有人曾尝试过覆盖 JavaScript 中的 alert() 函数吗?

  • 哪些浏览器支持此功能?
  • 哪些浏览器版本支持此功能?
  • 覆盖该函数存在哪些危险性?

那不是一个无限循环吗? - Pool
1
@Nick - 不是的。'正常'的window.alert函数将被分配给window._alert。在此之后,window.alert函数被重新定义。 - Chris Shouts
@roosteronacid:你的代码在语义和语法上都很好,尽管有些牵强,就像@paper1337指出的那样......那里没有递归的机会哈哈...本质上,你只是用 _alert 作为第一个实例中一种 expando 的临时方式来交换函数体。 - non sequitor
好的,我进行了回滚,以免混淆问题 :) - cllpse
12个回答

216

它绝对是“支持的”。这是你的网页,你可以随心所欲地处理。

我已经使用事件拦截技术来跟踪分析数据,而无需修改库文件。

使用代理模式:

(function(proxied) {
  window.alert = function() {
    // do something here
    return proxied.apply(this, arguments);
  };
})(window.alert);
你也可以绕过对原始函数的调用,如果你想要代理它。
更多信息请参考这里:JQuery Types #Proxy Pattern

在代理模式上加上+1,真正覆盖函数并确保它不会被篡改! - Josh Stodola
15
唉!在Internet Explorer 8上,window.alert不支持apply() - cllpse
很抱歉听到这个消息。applyFunction对象的一个方法。所以他们必须明确地将其限制为alert?! - Mike Gleason jr Couturier
4
他们一定使用代理模式覆盖了它 :D - Josh Stodola
旧版浏览器不支持此功能,会在“window.alert =”处抛出异常。 - Chris Pietschmann

23

虽然大多数浏览器支持重写alert函数,但你需要小心使用。

因为默认的提示框会阻塞执行线程,一些依赖此行为的库可能无法正常工作(充其量)。

你应该做一个好公民并避免接触原生API。如果你这样做了,当使用第三方代码时可能会破坏某些东西。

然而,如果你想在特定上下文中重新定义提示框行为,你可以使用匿名函数将其包含,像这样:

/* new funky alert */
function myFunkyAlert(msg) { 
    /* here goes your funky alert implementation */
    alert("Look ma!\n" + msg);
}

(function(alert) { // anonymous function redefining the "alert"

    /* sample code */
    alert("Hello World!");

})(myFunkyAlert);

18

覆盖警报函数没有任何隐患。每个浏览器都支持它。

例如:

// function over riding. Redirecting to Console with Firebug installed.
function alert(message) { 
    console.info(message);
} 

alert('This is an override.');

12
如果你的替代方案是非阻塞式的,可能存在风险。比如,调用 alert("Reloading") 并重新加载网页的代码。用户可能永远看不到警告文本。 - Darien

14

正如其他答案中所说,您可以通过覆盖该函数来实现

window.alert = null

或者

window.alert = function(){}

然而,这并不一定会覆盖Window构造函数原型上的函数(注意大写的 W),所以黑客仍然可以输入:

然而,这并不一定会覆盖Window构造函数原型上的函数(注意大写的 W),所以黑客仍然可以输入:

Window.prototype.alert.apply(window, ["You were hacked!"]);
因此,您还需要使用以下内容覆盖该函数:

Window.prototype.alert = null
或者
Window.prototype.alert = function(){}

这并不一定会覆盖其他框架中的函数。请参见http://jsfiddle.net/18znqbjd/1/。 - Robert
Robert:是的,而且原因很充分。不同的框架基本上是不同的HTML文档,每个文档都有自己的JavaScript“实例”。 - Rolf
1
你确定在2017年Window.prototype.alert仍然是一个函数吗? :P - iplus26

13

我认为每个JavaScript实现都会支持这个功能,而且它没有任何危险性。通常使用HTML/CSS来替换操作系统原始的提示框,从而达到更加优雅的效果。以这种方式实现意味着您不必更改现有代码!这个功能的存在使JavaScript变得很棒。


6

您好。针对IE8,您可以通过以下方式重新定义alert()函数:

/** 
 * Definition of global attached to window properties <br/>
 */ 
    (function() {
      nalert = window.alert;
      Type = {
          native: 'native',
          custom: 'custom'
      };
    })();

/**
 * Factory method for calling alert(). 
 * It will be call a native alert() or a custom redefined alert() by a Type param.
 * This defeinition need for IE
 */ 
    (function(proxy) {

          proxy.alert = function () {
          var message = (!arguments[0]) ? 'null': arguments[0];
          var type = (!arguments[1]) ? '': arguments[1];

          if(type && type == 'native') {
           nalert(message);
          }
          else {
               document.write('<h1>I am redefiend alert()<br/>Alert say: '+message+'</h1>');
          }     
      };
   })(this);

并称为
alert('Hello, hacker!');
nalert('I am native alert');
alert('Hello, user!', Type.custom);

4

现代浏览器中的所有JavaScript实现都支持覆盖。

危险很简单,如果你覆盖常用函数(如alert()),会让其他团队成员非常疯狂。

因此,除非你是将覆盖函数作为调试或以某种方式修改现有代码的工具,否则我不认为有任何理由这样做。只需创建一个新函数。


4

我的经验是,我们曾经使用覆盖alert()函数的方法来“黑客”试用版JavaScript库。该库会不时地通过弹出框显示“请注册!”。

我们只需定义自己的alert()函数,就可以轻松解决了。

这只是为了测试目的,后来我们购买了完整版本,所以没有任何不道德行为;-)


3

我曾经面临一个需求,需要在实际警告消息的同时显示一个默认消息。这是我处理它的方法。


    const actualAlertFunc = window.alert;
    window.alert = function(msg) {
         actualAlertFunc('some default message '+ msg);
    }

我已经在Chrome上测试过了。我不确定它是否是一个好的实践,但它达到了目的。


2

在Firefox和IE8中,它肯定有效。我认为它适用于任何浏览器。这基本上是JavaScript的基础,尽管我们不经常看到它与原生函数一起使用。


1
需要特别针对IE6浏览器进行定位,其他浏览器可能也可以。 - AnthonyWJones

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接