《第三方JavaScript编程》——1.4 第三方开发的挑战

简介: 不幸的是,这些挑战仅仅是冰山一角。第三方JavaScript的开发充满了陷阱,说到底,Web浏览器并非为嵌入式应用而生,也没有过多考虑第三方代码。浏览器日趋完善,且会引入一些新的特性,可以减轻一些第三方开发的负担,但仍旧是一场艰苦的战斗,且兼容旧的浏览器通常是任何类型的分布式应用都需要考虑的问题。

本节书摘来自异步社区《第三方JavaScript编程》一书中的第1章,第1.4节,作者:[美] Ben Vinegar Anton Kovalyov著,更多章节内容可以访问云栖社区“异步社区”公众号查看

1.4 第三方开发的挑战

你已经了解了第三方JavaScript是编写高度分发应用的一种强大方式。但是编写在其他人网站上执行的脚本,同传统的JavaScript编程相比有一系列独特的挑战。具体而言,你的代码将在一个完全不受控制、一个不同域的DOM环境中执行。这意味着你必须面对一些难以预料的复杂情况,比如未知的网页上下文,一个同其他第一方、第三方脚本共享的JavaScript环境,甚至浏览器的一些限制。我们快速的浏览一下涉及的挑战。

1.4.1 未知的上下文
当一个发布者在他们的Web页面中引入你的第三方JavaScript,通常你很少知道它被放置的上下文。你的脚本可能会被诸多不同文档声明,不同DOM布局的页面引入,而且应当在这些页面中都能正常工作。

你不得不考虑发布者可能在他们页面顶部的

标签中引入你的脚本,也可能会在底部引入。发布者也可能会在iframe中加载你的应用,也可能在一个标签完全废弃的页面中加载;在HTML5中,部分是可选的,而且并非所有浏览器都会在内部自动生成。如果你的脚本在查询或者操作DOM的时候用到了这些核心的元素,就会陷入麻烦了。

如果你在开发一个嵌入式微件,显示适当的样式也是一个需要被关注的问题。微件将被放置在一个浅色背景还是深色背景的Web页面中?你希望你的微件继承样式并“融入”发布者的页面设计吗?你希望你的微件在所有上下文中看起来都是一致的吗?如果发布者页面的HTML格式错误会出现什么情况,导致页面的渲染使用怪异模式吗?解决这些问题都需要精心编写CSS。我们会在后续的章节中给出这些问题的解决方案。

1.4.2 共享环境
对于一个给定的Web环境,只有一个全局变量的命名空间被页面上执行的每一段代码所共享。你不仅要注意不能让你的全局变量胡乱修改命名空间,也要明白其他脚本,可能是同你一样的第三方应用,也能够修改你可能依赖的标准的对象和原型。

例如,全局的JSON对象。在现代浏览器中,这是一个原生的浏览器对象,可以极快地解析和序列化JSON(JavaScript对象表示方法)。不幸的是,它可以很容易地被任何人修改。如果你的应用依赖于这个对象的正常工作,并且它被其他代码改为了不兼容的方式,你的应用可能会产生不正确的结果甚至崩溃。

下面的示例代码演示了使用简单的变量赋值修改全局的JSON对象。
screenshot
你自己可能会这么想,“为什么会有人这么做?”Web开发者往往加载他们自己的JSON方法来支持旧的浏览器没有提供的本地方法。但是有些这样的库不兼容。例如,很流行的Prototype JavaScript库在旧版本提供的JSON方法同原生方法相比,在处理undefined值时的输出并不相同,如下。
screenshot
JSON对象只是浏览器原生对象可以被客户端代码改变的一个例子;还有数百种其他的对象。在本书中,我们会寻找恢复或者简单避免这些对象的解决方法。

同样,DOM是另外一个你不得不担心的全局应用程序命名空间。对于一个给定的Web页面而言,只有一个DOM树,并且它是被当前页面上运行的所有应用所共享。这就要求你操作它的时候要格外注意。任何插入到DOM的新元素需要同现有的元素和平共存,并且不干扰其他查询DOM的脚本执行。同样,如果范围不当,你的DOM查询也可能会意外的选择到不属于你的元素。反之亦然,如果你没有认真地选择唯一的ID和类名,其他应用也可能不经意间会查询到你的元素。

因为你的代码同其他脚本同属于相同的执行环境,安全性也是要考虑的。不仅要防止你的用户使用不当,还需要考虑页面上的其他脚本,甚至发布者也是一个潜在的威胁。例如,如果你在为一个大型的、受欢迎的服务编写微件或者脚本(像一个社交网站),发布者或许会有很浓厚的兴趣去尝试在他们的页面上做一个假的交互界面。

1.4.3 浏览器限制
如果一个未知的文档上下文,多个全局命名空间,以及额外的安全问题还不够糟糕,Web浏览器禁止某些行为经常会影响到第三方脚本。例如,AJAX已然成为Web开发人员无刷新获取和提交数据的一个主要工具。但是Web浏览器的同源策略限制了XMLHttpRequest跨域进行通信,如图1.9所示。如果你正在编写第三方脚本,且需要同你的域所在的应用进行数据通信,那么你就不得不通过其他方式实现了。
screenshot
同样,Web浏览器通常也会限制应用程序读写第三方Cookies。如此一来,你的用户将无法“登录”你的应用或者记住后续请求的动作。根据应用的复杂度,无法读写第三方Cookies可能是一个真正的障碍。

不幸的是,这些挑战仅仅是冰山一角。第三方JavaScript的开发充满了陷阱,说到底,Web浏览器并非为嵌入式应用而生,也没有过多考虑第三方代码。浏览器日趋完善,且会引入一些新的特性,可以减轻一些第三方开发的负担,但仍旧是一场艰苦的战斗,且兼容旧的浏览器通常是任何类型的分布式应用都需要考虑的问题。

但是不必担心。你购买了本书,已经做了一个很好的决定,它包含了第三方JavaScript代码所面临的问题。作为回报,我们将会告诉你如何解决这些问题。

相关文章
|
30天前
|
开发框架 JavaScript 安全
js开发:请解释什么是Express框架,以及它在项目中的作用。
Express是Node.js的Web开发框架,简化路由管理,支持HTTP请求处理。它采用中间件系统增强功能,如日志和错误处理,集成多种模板引擎(EJS、Jade、Pug)用于HTML渲染,并提供安全中间件提升应用安全性。其可扩展性允许选用合适插件扩展功能,加速开发进程。
|
30天前
|
缓存 JavaScript 前端开发
js开发:请解释什么是Webpack,以及它在项目中的作用。
Webpack是开源的JavaScript模块打包器,用于前端项目构建,整合并优化JavaScript、CSS、图片等资源。它实现模块打包、代码分割以提升加载速度,同时进行资源优化和缓存。借助插件机制扩展功能,并支持热更新,加速开发流程。
20 4
|
30天前
|
缓存 JavaScript 数据安全/隐私保护
js开发:请解释什么是ES6的Proxy,以及它的用途。
`ES6`的`Proxy`对象用于创建一个代理,能拦截并自定义目标对象的访问和操作,应用于数据绑定、访问控制、函数调用的拦截与修改以及异步操作处理。
17 3
|
1天前
|
JavaScript 前端开发
js开发:请解释事件冒泡和事件捕获。
JavaScript中的事件处理有冒泡和捕获两种方式。事件冒泡是从子元素向上级元素传递,而事件捕获则从外层元素向内层传递。`addEventListener`的第三个参数可设定事件模式,`false`或不设为冒泡,`true`为捕获。示例代码展示了如何设置。
13 2
|
8天前
|
开发框架 前端开发 JavaScript
采用C#.Net +JavaScript 开发的云LIS系统源码 二级医院应用案例有演示
技术架构:Asp.NET CORE 3.1 MVC + SQLserver + Redis等 开发语言:C# 6.0、JavaScript 前端框架:JQuery、EasyUI、Bootstrap 后端框架:MVC、SQLSugar等 数 据 库:SQLserver 2012
|
30天前
|
Web App开发 JavaScript 前端开发
js开发:请解释什么是Node.js,以及它的应用场景。
Node.js是基于V8的JavaScript运行时,用于服务器端编程。它的事件驱动、非阻塞I/O模型使其在高并发实时应用中表现出色,如Web服务器、实时聊天、API服务、微服务、工具和跨平台桌面应用(使用Electron)。适用于高性能和实时需求场景。
18 4
|
30天前
|
JavaScript 前端开发 编译器
js开发: 请解释什么是Babel,以及它在项目中的作用。
**Babel是JavaScript编译器,将ES6+代码转为向后兼容版本,确保在旧环境运行。它在前端构建中不可或缺,提供语法转换、插件机制、灵活配置及丰富的生态系统,支持代码兼容性和自定义编译任务。**
17 6
|
30天前
|
JavaScript 前端开发
js开发:请解释什么是ES6的async/await,以及它如何解决回调地狱问题。
ES6的`async/await`是基于Promise的异步编程工具,能以同步风格编写异步代码,提高代码可读性。它缓解了回调地狱问题,通过将异步操作封装为Promise,避免回调嵌套。错误处理更直观,类似同步的try...catch。
|
30天前
|
JavaScript
js开发:请解释什么是ES6的Generator函数,以及它的用途。
ES6的Generator函数是暂停恢复的特殊函数,用yield返回多个值,适用于异步编程和流处理,解决了回调地狱问题。
16 6
|
30天前
|
存储 JavaScript 索引
js开发:请解释什么是ES6的Map和Set,以及它们与普通对象和数组的区别。
ES6引入了Map和Set数据结构。Map的键可为任意类型,有序且支持get、set、has、delete操作;Set存储唯一值,提供add、delete、has方法。两者皆可迭代。示例展示了Map和Set的基本用法,如添加、查询、删除元素。
15 2