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对象。
你自己可能会这么想,“为什么会有人这么做?”Web开发者往往加载他们自己的JSON方法来支持旧的浏览器没有提供的本地方法。但是有些这样的库不兼容。例如,很流行的Prototype JavaScript库在旧版本提供的JSON方法同原生方法相比,在处理undefined值时的输出并不相同,如下。
JSON对象只是浏览器原生对象可以被客户端代码改变的一个例子;还有数百种其他的对象。在本书中,我们会寻找恢复或者简单避免这些对象的解决方法。
同样,DOM是另外一个你不得不担心的全局应用程序命名空间。对于一个给定的Web页面而言,只有一个DOM树,并且它是被当前页面上运行的所有应用所共享。这就要求你操作它的时候要格外注意。任何插入到DOM的新元素需要同现有的元素和平共存,并且不干扰其他查询DOM的脚本执行。同样,如果范围不当,你的DOM查询也可能会意外的选择到不属于你的元素。反之亦然,如果你没有认真地选择唯一的ID和类名,其他应用也可能不经意间会查询到你的元素。
因为你的代码同其他脚本同属于相同的执行环境,安全性也是要考虑的。不仅要防止你的用户使用不当,还需要考虑页面上的其他脚本,甚至发布者也是一个潜在的威胁。例如,如果你在为一个大型的、受欢迎的服务编写微件或者脚本(像一个社交网站),发布者或许会有很浓厚的兴趣去尝试在他们的页面上做一个假的交互界面。
1.4.3 浏览器限制
如果一个未知的文档上下文,多个全局命名空间,以及额外的安全问题还不够糟糕,Web浏览器禁止某些行为经常会影响到第三方脚本。例如,AJAX已然成为Web开发人员无刷新获取和提交数据的一个主要工具。但是Web浏览器的同源策略限制了XMLHttpRequest跨域进行通信,如图1.9所示。如果你正在编写第三方脚本,且需要同你的域所在的应用进行数据通信,那么你就不得不通过其他方式实现了。
同样,Web浏览器通常也会限制应用程序读写第三方Cookies。如此一来,你的用户将无法“登录”你的应用或者记住后续请求的动作。根据应用的复杂度,无法读写第三方Cookies可能是一个真正的障碍。
不幸的是,这些挑战仅仅是冰山一角。第三方JavaScript的开发充满了陷阱,说到底,Web浏览器并非为嵌入式应用而生,也没有过多考虑第三方代码。浏览器日趋完善,且会引入一些新的特性,可以减轻一些第三方开发的负担,但仍旧是一场艰苦的战斗,且兼容旧的浏览器通常是任何类型的分布式应用都需要考虑的问题。
但是不必担心。你购买了本书,已经做了一个很好的决定,它包含了第三方JavaScript代码所面临的问题。作为回报,我们将会告诉你如何解决这些问题。