JavaScript在网页开发中应用广泛吗?

2026-04-27 20:001阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1961个文字,预计阅读时间需要8分钟。

JavaScript在网页开发中应用广泛吗?

目录 + 引用 + iframe + 基本通信 + 基本的 HTML 结构 + 使用 JavaScript + 在窗口间发送消息 + 注意事项 + 类型 + 如何传递函数并执行 + 如何在父窗口访问子窗口的 console + 引用 + 最近完善了 easyjobs 代码

目录
  • 引言
  • iframe 基本通信
    • 基本的 HTML 结构
    • 使用 JavaScript 在窗口之间发送消息
  • 注意事项
    • 类型
    • 如何传递函数并执行
  • 如何在父窗口访问到子窗口的 console

    引言

    我最近在完善 easyjobs 代码共享的功能。

    左侧是代码编辑器,右侧下方有一个控制台。

    当我们在左侧编辑完成代码后,点击运行 JS,右侧的控制台就可以输出内容。

    而右侧上方有一个渲染画布,用来作为代码运行的容器。

    你可以打开网址尝试:www.easyjobs.biz/code-sharin…。

    因为同时需要运行 JavaScript 代码,所以需要对环境进行隔离。也就是要有一个独立的 JavaScript 运行环境,也可以叫做沙箱。

    该怎么做呢?

    实现 JavaScript 沙箱的方案有很多,比如 iframe、with+Proxy、还有基于 Object.freeze 的不成熟提案,如果不涉及 Web API 的话,甚至可以借助 nodejs 的 vm 模块。

    不过 JavaScript 沙箱不是本文的重点。我的场景决定了 iframe 是最好的选择,因为我不仅仅需要隔离 JS 代码,还要隔离 HTML 和 CSS 代码。

    如何做沙箱呢?

    iframe 有一个 srcdoc 属性,把要执行的代码传给它就可以了。

    <iframe srcdoc="<script>alert('hello')</script>"></iframe>

    为了方便查看 iframe 中 console 输出的内容,我们还需要想办法接收 iframe 传递过来的消息。

    这也就是本文的主要内容,iframe 通信实战。

    iframe 基本通信

    我在这里用代码来演示一下 iframe 最基本的通信是如何做的。

    基本的 HTML 结构

    首先我们有一个 index.html 文件。

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>父窗口</title> </head> <body> <p>父窗口</p> <iframe src="./sub.html"></iframe> <button onclick="sendMessage()">发送一条消息给子窗口</button> <p id="response"></p> </body> </html>

    然后有一个 sub.html。

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>子窗口</title> </head> <body> <p>子窗口</p> <button onclick="sendMessage()">发送一条消息给父窗口</button> <p id="response"></p> </body> </html>

    它们的关系就是相互嵌套的关系。

    打开 index.html,大概是下面这样。

    需要注意,多窗口通信需要使用 http(s) 协议。

    JavaScript在网页开发中应用广泛吗?

    使用 JavaScript 在窗口之间发送消息

    我们来实现一下父窗口的 sendMessage 方法。

    let sub = window.frames[0] function sendMessage() { sub.postMessage({ msg: "来自父窗口的一条消息" }) }

    其中 window.frames 是获取当前窗口的所有 iframe 元素,它返回一个类似数组的结构。

    通过调用 sub 的 postMessage 方法可以传递消息。

    然后我们来到 sub.html 中编写接收端的代码。

    const responseEl = document.getElementById("response") window.addEventListener("message", function (e) { responseEl.innerHTML += `收到一条消息:${e.data.msg}` })

    接收端使用 window.addEventListener 来监听 message 事件。当有其他窗口通过 poseMessage 来向当前窗口发送消息时,会触发这个事件。

    我们来点击父窗口的「发送一条消息给子窗口」按钮。

    可以看到子窗口可以打印父窗口的消息。

    同理,我们也可以通过 parent.postMessage 反向向父窗口传递消息。

    在 sub.html 中继续增加 sendMessage 代码。

    function sendMessage() { parent.postMessage({ msg: "来自子窗口的一条消息" }) }

    这个代码和 index.html 中发送消息的代码很相似,唯一的区别就是接受者变成了 parent。parent 就是指当前窗口的父窗口。

    回到 index.html 中,增加监听代码。监听代码与子窗口完全一致,可以直接复制过来。

    const responseEl = document.getElementById("response") window.addEventListener("message", function (e) { responseEl.innerHTML += `收到一条消息:${e.data.msg}</br>` })

    我们来点击子窗口的「发送一条消息给父窗口」按钮。

    这样就实现了 iframe 窗口间双向通信。

    注意事项

    类型

    需要注意的是,postMessage 仅支持 JSON 支持的类型。

    • string
    • number
    • null
    • boolean
    • object
    • array

    如果传递 undefined 的话,会自动转成 null。

    除了上述类型以外的其他类型都不支持,比如 function、symbol。如果传递了这些类型,浏览器会报错。

    如何传递函数并执行

    传递函数是一个很常见的需求,我们可以通过把函数转换为字符串的方式进行传递。

    比如下面这样:

    function fn () {} sub.postMessage({ fn: fn.toString() })

    在接收方只需要通过 eval 就可以调用函数字符串了。

    不过如果函数内引用了外部变量的话,那就不行了。

    比如下面这样:

    let name = '代码与野兽' function fn () { console.log(name) } sub.postMessage({ fn: fn.toString() })

    因为接收端无法获取到发送端的变量。

    如果碰巧接收端也存在 name 这个变量的话,eval 在执行时就会访问到接收端的变量而非发送端的变量。

    这里也体现出了纯函数的优势。如果我们遵循函数式编程范式编写了纯函数,就不会导致这个问题。

    如何在父窗口访问到子窗口的 console

    回到文章开头,虽然我们可以通过 iframe 通信来传递消息,但实现 iframe 执行 console 同步到父窗口,仍然是个问题。

    其实非常简单,把 console 对象上的所有方法劫持,然后把这段代码加入到 iframe 最顶部就可以了。

    var fns = new Map() for(let key in console) { fns.set(key, console[key]) console[key] = (...args) => { funcToString(args) window.parent.postMessage({ type: 'console.' + key, args }, "*") return fns.get(key)(...args) } }

    其中会调用 funcToString 方法,这个方法就是把所有的 function 字符串化。

    因为我们不确定传入的结构的嵌套深度,所以需要使用递归来转换。

    function funcToString(args) { Object.keys(args).forEach((key) => { const arg = args[key] if (typeof arg === "function") { args[key] = arg.toString() } else if (typeof arg === "object") { funcToString(arg) } }) }

    以上就是JavaScript iframe 实现多窗口通信实例详解的详细内容,更多关于JavaScript iframe多窗口通信的资料请关注易盾网络其它相关文章!

    本文共计1961个文字,预计阅读时间需要8分钟。

    JavaScript在网页开发中应用广泛吗?

    目录 + 引用 + iframe + 基本通信 + 基本的 HTML 结构 + 使用 JavaScript + 在窗口间发送消息 + 注意事项 + 类型 + 如何传递函数并执行 + 如何在父窗口访问子窗口的 console + 引用 + 最近完善了 easyjobs 代码

    目录
    • 引言
    • iframe 基本通信
      • 基本的 HTML 结构
      • 使用 JavaScript 在窗口之间发送消息
    • 注意事项
      • 类型
      • 如何传递函数并执行
    • 如何在父窗口访问到子窗口的 console

      引言

      我最近在完善 easyjobs 代码共享的功能。

      左侧是代码编辑器,右侧下方有一个控制台。

      当我们在左侧编辑完成代码后,点击运行 JS,右侧的控制台就可以输出内容。

      而右侧上方有一个渲染画布,用来作为代码运行的容器。

      你可以打开网址尝试:www.easyjobs.biz/code-sharin…。

      因为同时需要运行 JavaScript 代码,所以需要对环境进行隔离。也就是要有一个独立的 JavaScript 运行环境,也可以叫做沙箱。

      该怎么做呢?

      实现 JavaScript 沙箱的方案有很多,比如 iframe、with+Proxy、还有基于 Object.freeze 的不成熟提案,如果不涉及 Web API 的话,甚至可以借助 nodejs 的 vm 模块。

      不过 JavaScript 沙箱不是本文的重点。我的场景决定了 iframe 是最好的选择,因为我不仅仅需要隔离 JS 代码,还要隔离 HTML 和 CSS 代码。

      如何做沙箱呢?

      iframe 有一个 srcdoc 属性,把要执行的代码传给它就可以了。

      <iframe srcdoc="<script>alert('hello')</script>"></iframe>

      为了方便查看 iframe 中 console 输出的内容,我们还需要想办法接收 iframe 传递过来的消息。

      这也就是本文的主要内容,iframe 通信实战。

      iframe 基本通信

      我在这里用代码来演示一下 iframe 最基本的通信是如何做的。

      基本的 HTML 结构

      首先我们有一个 index.html 文件。

      <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>父窗口</title> </head> <body> <p>父窗口</p> <iframe src="./sub.html"></iframe> <button onclick="sendMessage()">发送一条消息给子窗口</button> <p id="response"></p> </body> </html>

      然后有一个 sub.html。

      <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>子窗口</title> </head> <body> <p>子窗口</p> <button onclick="sendMessage()">发送一条消息给父窗口</button> <p id="response"></p> </body> </html>

      它们的关系就是相互嵌套的关系。

      打开 index.html,大概是下面这样。

      需要注意,多窗口通信需要使用 http(s) 协议。

      JavaScript在网页开发中应用广泛吗?

      使用 JavaScript 在窗口之间发送消息

      我们来实现一下父窗口的 sendMessage 方法。

      let sub = window.frames[0] function sendMessage() { sub.postMessage({ msg: "来自父窗口的一条消息" }) }

      其中 window.frames 是获取当前窗口的所有 iframe 元素,它返回一个类似数组的结构。

      通过调用 sub 的 postMessage 方法可以传递消息。

      然后我们来到 sub.html 中编写接收端的代码。

      const responseEl = document.getElementById("response") window.addEventListener("message", function (e) { responseEl.innerHTML += `收到一条消息:${e.data.msg}` })

      接收端使用 window.addEventListener 来监听 message 事件。当有其他窗口通过 poseMessage 来向当前窗口发送消息时,会触发这个事件。

      我们来点击父窗口的「发送一条消息给子窗口」按钮。

      可以看到子窗口可以打印父窗口的消息。

      同理,我们也可以通过 parent.postMessage 反向向父窗口传递消息。

      在 sub.html 中继续增加 sendMessage 代码。

      function sendMessage() { parent.postMessage({ msg: "来自子窗口的一条消息" }) }

      这个代码和 index.html 中发送消息的代码很相似,唯一的区别就是接受者变成了 parent。parent 就是指当前窗口的父窗口。

      回到 index.html 中,增加监听代码。监听代码与子窗口完全一致,可以直接复制过来。

      const responseEl = document.getElementById("response") window.addEventListener("message", function (e) { responseEl.innerHTML += `收到一条消息:${e.data.msg}</br>` })

      我们来点击子窗口的「发送一条消息给父窗口」按钮。

      这样就实现了 iframe 窗口间双向通信。

      注意事项

      类型

      需要注意的是,postMessage 仅支持 JSON 支持的类型。

      • string
      • number
      • null
      • boolean
      • object
      • array

      如果传递 undefined 的话,会自动转成 null。

      除了上述类型以外的其他类型都不支持,比如 function、symbol。如果传递了这些类型,浏览器会报错。

      如何传递函数并执行

      传递函数是一个很常见的需求,我们可以通过把函数转换为字符串的方式进行传递。

      比如下面这样:

      function fn () {} sub.postMessage({ fn: fn.toString() })

      在接收方只需要通过 eval 就可以调用函数字符串了。

      不过如果函数内引用了外部变量的话,那就不行了。

      比如下面这样:

      let name = '代码与野兽' function fn () { console.log(name) } sub.postMessage({ fn: fn.toString() })

      因为接收端无法获取到发送端的变量。

      如果碰巧接收端也存在 name 这个变量的话,eval 在执行时就会访问到接收端的变量而非发送端的变量。

      这里也体现出了纯函数的优势。如果我们遵循函数式编程范式编写了纯函数,就不会导致这个问题。

      如何在父窗口访问到子窗口的 console

      回到文章开头,虽然我们可以通过 iframe 通信来传递消息,但实现 iframe 执行 console 同步到父窗口,仍然是个问题。

      其实非常简单,把 console 对象上的所有方法劫持,然后把这段代码加入到 iframe 最顶部就可以了。

      var fns = new Map() for(let key in console) { fns.set(key, console[key]) console[key] = (...args) => { funcToString(args) window.parent.postMessage({ type: 'console.' + key, args }, "*") return fns.get(key)(...args) } }

      其中会调用 funcToString 方法,这个方法就是把所有的 function 字符串化。

      因为我们不确定传入的结构的嵌套深度,所以需要使用递归来转换。

      function funcToString(args) { Object.keys(args).forEach((key) => { const arg = args[key] if (typeof arg === "function") { args[key] = arg.toString() } else if (typeof arg === "object") { funcToString(arg) } }) }

      以上就是JavaScript iframe 实现多窗口通信实例详解的详细内容,更多关于JavaScript iframe多窗口通信的资料请关注易盾网络其它相关文章!