为什么遵循W3C标准极其重要?

公司里一个IE only的项目里遇到个bug,有的测试人员遇到了,而作为开发人员的我却没遇到。我查了1天也没找出原因,倒是发现其中混杂着各种风格的代码。
以根据id获取DOM元素为例,我就找到4种方式:
  1. document.getElementById(elementId):W3C标准。
  2. document.all[elementId]或document.all.elementId:这个方法会返回id或name为elementId的元素(或元素数组)。IE、Chrome和Opera支持,Firefox不支持。
  3. window[elementId]或window.elementId:DOM元素会根据其id生成一个全局变量。IE、Chrome和Opera支持,Firefox不支持。
  4. eval(elementId, window):同上。IE、Chrome和Opera支持,Firefox不支持。

在兼容性方面,document.getElementById()无疑是最好的方法,所有的浏览器都支持。
可惜IE 6有个奇葩的bug,会把表单控件(如input元素)的name和id混淆,因此可能得到错误的DOM元素。
一个粗略的解决办法如下:
function getElementById(elementId) {
	var element = document.getElementById(elementId);
	if (element && element.id != elementId) {
		var elements = document.all[elementId];
		var length = elements.length;
		for (var i = 0; i < length; ++i) {
			element = elements[i];
			if (element.id == elementId) {
				return element;
			}
		}
		return null;
	} else {
		return element;
	}
}
本来一行代码能解决的问题,居然要10多行才能实现,坑爹啊有木有?

别忘了这还只是粗略的解决办法,当元素的id为数字时,你会发现这个函数就失效了。原因就是document.all是个拟数组对象,以数字做键名时(无论是1,还是"1"),会被当成数字索引。
另外,document.all[elementId]也可能返回3种结果:当没有符合的元素时,它是null;当只有1个元素时,它就是这个元素;当有多个符合的元素(id或name相符)时,它是这些元素组成的数组。好在这个例子中,前2种情况已经被(element && element.id != elementId)排除了,所以才能直接当成数组来遍历。
这些恼人的兼容性代码就是浏览器不遵循W3C标准所招致的后果,而这些后果在IE的各个版本中比比皆是。

这还仅是浏览器的问题,别忘了开发者自己也是帮凶。
前面说了,公司的这个项目是IE only的,所以上述4种方法是都可行的,于是继续看剩下的2种方法。

这个window[elementId]看上去确实方便,不过当elementId为数字时,它也同样歇菜了。
再进一步,考虑一下如果elementId为'document'、'alert'或'NaN'会怎样?这些内置的全局变量当然不会被DOM元素覆盖,因此你自然拿不到想要的DOM元素。
再考虑一个问题,我们解析JSON时会尝试使用JSON.parse()方法:
function parseJSON(jsonString) {
	return window.JSON ? JSON.parse(jsonString) : eval(jsonString);
}
这个方法一直工作正常,直到某天你弄了个id为JSON的HTML元素…
为了向下兼容那些老掉牙的浏览器,这种判断方式在JavaScript代码中大量存在,例如XMLHttpRequest。

继续看eval(elementId, window),它也继承了window[elementId]的所有毛病。
更囧的是项目里还不是用我这种严谨的写法,而是直接写成eval(elementId)。也就是在当前作用域查找名字为elementId的变量,找不到时才通过作用域链向上查找,直到全局作用域。因此很可能一个内部变量就将逻辑完全破坏了:
function test() {
	var form = 1;
	function getElementById(elementId) {
		return eval(elementId);
	}
	return getElementById('form') == document.getElementById('form');
}

正是因为开发者想少写几个字来取代冗长的document.getElementById(),才会让这些坑爹的代码流行起来。
然而W3C标准并不是为了让开发者感到不便才产生的,而是经过了深思熟虑,才把那些不合理的东西去掉的。
顽固地抱持着那些不合理的部分,执意地扭曲标准,最后只会让我这种擦屁股的倒霉鬼完全迷失在糟粕之中,继而愤世嫉俗地控诉这些蛋疼的琐事。

其实IE在诞生之初并没有W3C标准,所以它可以自己定义API——尽管现在看来很多都不恰当。而在它如日中天的时代,很多开发者就把它当成了事实上的标准。于是在W3C标准建立之后,IE并没有抛弃私有的API,而是为了向后兼容而一错到底,这就错过了纠正错误的最佳时机。
之后出现的Firefox让web开发者们看到了曙光,他们发现支持W3C标准后可以消除很多bug。然而Mozilla对W3C标准太过执着,在尚未完全遵循标准时,就舍弃了很多方便的功能(例如text-overflow: ellipsis),这就让需要兼容性的人们比较为难了。
其后出现的Chrome则最为狡猾,它知道如何正确地取舍API(例如安全和隐私方面不能妥协,其他见机行事)。在尽可能遵循W3C标准的同时,它也根据需要实现非标准的API;再以Google的影响力,让其融入新的W3C标准。而其中最重要的一点就是频繁更新:让用户只能使用最新的版本,这就保证了可以尽可能地遵循标准和减少bug。(当然,Chrome支持后3种方式显然是不对的;但为了靠兼容性来抢占市场,它仍然这么做了。)
如今Firefox也终于意识到了这个问题,可惜赶上Chrome还需时日。
最无可救药的就是IE了,更新缓慢,不积极淘汰过时的浏览器,每个新版本都要保留向下兼容模式——这就让错误日积月累,不断严重了。

联想到当今的社会现象,虽然毒瘤的存在是客观事实,大多数人都能认识到这点,但却没人对其动刀,甚至争先恐后地中毒,以致其越来越病入膏肓。
其实只要建立一个绝大部分人向往的新规则,让所有人共同遵循,毒瘤就不攻自破了。
在这个过程中,最重要的是从自己做起,坚定信念和保持希望,并传播给他人。时间可以洗刷和净化罪恶,但有了人们的积极参与,这个过程可以大幅缩短。

希望开发者们都能认识到并勇于肩负起自己的责任。以最低俗的方式解释的话就是:你的薪水和你承担的责任成正比。

最后为避免走题,回答一下本文的标题:标准的重要性不在于它是标准,而在于大家都遵循它。没人遵守的标准一点都不重要,例如天朝宪法。

你可能感兴趣的:(w3c,标准)