【问题标题】:Is there a way to find out which iframe is calling a parent's JavaScript function有没有办法找出哪个 iframe 正在调用父级的 JavaScript 函数
【发布时间】:2019-06-14 07:36:53
【问题描述】:

这是一个例子

父.html

<script>
function printWhoCalledMe() {
  console.log(???);  // what goes here that will identify the caller?
}
<iframe src="iframe1.html"></iframe>
<iframe src="iframe2.html"></iframe>

iframe1.html

<script>
window.parent.printWhoCalledMe();
</script>

iframe2.html

<script>
window.parent.printWhoCalledMe();
</script>

更大的问题是I have a test harness that runs a bunch of tests, one at a time, in an iframe。每次测试调用window.parent.reportOnTest(success)

我正在研究通过在超过 1 个 iframe 中运行测试来并行化测试,但我必须通过每个测试,目前是 1000 个测试,并将它们的调用从 window.parent.reportOnTest(success) 更改为 window.parent.reportOnTest(success, window.location.href) 之类的东西像这样。

我想知道是否有办法在不修改测试的情况下找出哪个测试正在调用父级。

注意:我试过了

function printWhoCalledMe() {
  console.log(window.location.href);
}

但这会打印父级的 href。

【问题讨论】:

  • 可能值得通过arguments.callee.caller 进行调查,但我不确定该函数的窗口对象是否可以通过该路径获得。

标签: javascript html iframe


【解决方案1】:

我担心你可能不得不使用这样的字符串值..

function printWhoCalledMe(callerPage) {
  console.log(callerPage);  // what goes here that will identify the caller?
}

您可以从您的子框架中使用类似的参数调用此函数..

iframe1.html

<script>
window.parent.printWhoCalledMe("iframe1");
</script>

iframe2.html

<script>
window.parent.printWhoCalledMe("iframe2");
</script>

【讨论】:

    【解决方案2】:

    如果您使用apply 调用您的父函数,您可以将上下文更改为框架window

    window.parent.printWhoCalledMe.apply(this);
    
    function printWhoCalledMe() {
      console.log(this); // this now refers to the frame window
    }
    

    【讨论】:

      【解决方案3】:

      太老套了,但你可以使用这样的东西:

      1. 使用caller 获取对调用所需函数的函数的引用。
      2. 继续使用Object.getPrototypeOf,直到达到该领域的Object.prototype
      3. 迭代所有框架窗口,并比较Object.prototype
      4. 找到匹配项后,使用 frameElement 获取 iframe。

      这需要同源、无沙盒和草率模式。示例:

      window.func = function func() {
        var proto, nextProto = func.caller;
        while (nextProto) {
          proto = nextProto;
          nextProto = Object.getPrototypeOf(proto);
        }
        var win = [].find.call(window.frames, function(win) {
          try {
            return win.Object.prototype === proto;
          } catch(err) {
            return false;
          }
        });
        if (win) {
          var iframe = win.frameElement;
          console.log("function called from frame " + iframe.name);
        }
      };
      var iframe = document.createElement('iframe');
      iframe.name = "myframe";
      document.body.appendChild(iframe);
      var doc = iframe.contentDocument;
      var script = doc.createElement('script');
      script.text = "(function f(){parent.func()})()";
      doc.body.appendChild(script);
      // Logs "function called from frame myframe"
      

      【讨论】:

        【解决方案4】:

        在调用父函数时,如果不将其包含在参数中,则无法获取此信息。

        幸运的是,这很容易。假设您给每个 iframe 一个 id,您只需将 iframe 的 id 传递给您正在调用的函数。您可以像这样获取您所在的 iframe 的 id:window.frameElement.id

        例如:

        iframe1.html

        <script>
            window.parent.printWhoCalledMe(window.frameElement.id);
        </script>
        

        父.html

        <script>
            function printWhoCalledMe(iframeId) {
                console.log(iframeId);  // Prints the id of the iframe that called the function
            }
        </script>
        

        【讨论】:

          猜你喜欢
          • 2014-02-22
          • 2015-05-31
          • 1970-01-01
          • 2012-04-17
          • 2011-01-21
          • 2018-08-10
          • 1970-01-01
          • 2010-11-16
          • 1970-01-01
          相关资源
          最近更新 更多