摘要:更多详情请看下面例举了日常前段开发中遇到的场景,解决方案有很多,但从开发阶段就进行规范,可以很大程度避免很多后续的潜在和兼容问题。
更多详情请看http://blog.zhangbing.club/%E...
下面例举了日常前段开发中遇到的场景,解决方案有很多,但从开发阶段就进行规范,可以很大程度避免很多后续的潜在和兼容问题。
获取body元素非标准做法
document.body
W3C规范方法
document.getElementsByTagName("body").item(0)
使用jQuery/Zepto
$("body");获取窗口标题
非标准做法
document.title
W3C规范方法
document.getElementsByTagName("title").item(0).innerHTML
使用jQuery/Zepto
$("title").text()监听iframe的加载完成事件
写法1:
iframe.onload = function() {...}
问题:存在兼容性问题,IE6、7无效
写法2:
iframe.onload = iframe.onreadystatechange = function(){...}
问题:逻辑复杂,事件绑定逻辑混乱,在某些浏览器上onload和onreadystatechange都会触发,需要另外加标记位判断,逻辑复杂。
简洁而完全兼容的写法:
var bindIframeOnloadEvent = function(el, onload) { if (el.attachEvent){ el.attachEvent("onload", onload); } else { el.onload = onload; } }; bindIframeOnloadEvent(iframe, function(){...});如何操作iframe内部的window
写法1:
iframe.contentWindow
问题: 部分浏览器不兼容(IE67),获取失败
写法2:
document.frames[frameId]
问题: 非标准调用,兼容性是问题,强制必须为iframe添加ID。
简洁而完全兼容的写法:
var getIframeWindow = function(el) { return el.contentWindow || el.contentDocument.parentWindow; }; var win = getIframeWindow(iframe);设置iframe的边框
写法1:
iframe.boder = 0;
问题: 非W3C标准,后面很可能废弃,部分浏览器不一定支持
写法2:
iframe.style.boder = "none";
问题: 完全依赖CSS控制,但存在兼容性问题,IE继续头疼
最终解决方案:
iframe.boder = 0; iframe.style.boder = "none";如何在a标签上绑定鼠标点击事件
写法1:
test
问题:
不符合CSP规范
等价于全局eval。只能调用公开的全局方法,污染全局变量
鼠标悬停时,状态栏会显示要运行的代码?!这对最终用户不友好
运行代码的上下文是window对象,和事件处理模型相违背
写法2:
test
问题:
不符合CSP规范
onclick和href在部分浏览器(IE继续躺枪)行文诡异,执行冲突异常
等价于全局eval。只能调用公开的全局方法,污染全局变量(原因同写法1)
写法3:
test
问题:只解决了问题2,其余问题仍存在
标准写法:
test
使用jQuery/Zepto亦可,存在唯一的小问题是鼠标指针不是手形,是默认。可采用CSS样式来解决cursor:pointer 。
script标签的书写方法深挖要点
script标签的type属性不是必须的,默认缺省就是text/javascript
script标签的language属性完全无用(asp时代微软似乎使用该属性来标记服务端语言是vb还是c#),不要画蛇添足
动态创建的script标签必须要指定type="text/javascript",否则JS不会执行
var script = document.createElement("script"); script.type = "text/javascript"; script.src = "###"; document.getElementsByTagName("body").item(0).appendChild(script);
动态创建的script追加动作是异步的,并不会立刻取得script运行结果,如果要等待加载完成需要监听完成事件
使用非标准或者比较新的属性需要格外注意,不要使代码逻辑依赖于这些特性。如defer/async属性
使用script.onerror来监听脚本执行失败的情况(语法错误,初始化运行时错误等都会触发)
监听script的完成事件比较复杂。
varbindScriptOnloadEvent = function(script, onload) { var done = false; script.onload = script.onreadystatechange = function() { if (!done && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete")) { done = true; script.onload = script.onreadystatechange = null; onload(); } }; }; bindScriptOnloadEvent(script, function(){...});
需要考虑兼容性,所以代码较多
substr函数不要使用原因:非标准,在部分浏览器报错,甚至连我的Android4.0上的浏览器都不认该函数
替代方案:使用substring函数。
jQuery/Zepto选择器的.text()和.html()方法现状:大多数开发同学会混淆两者并乱用,不清楚何时用哪个
详解:.text()方法用于获取和设置文本内容,.html()方法用户获取和设置HTML内容,当要设置或获取的内容仅仅为文本时,两者行为完全相同,但要操作的文本内容是HTML时,行为有着本质区别。
总结:
根据实际需要选择使用哪个方法,如能断定内容为纯文本请使用text()方法。仅当确实需要渲染HTML时才用html()方法
从安全角度,text()方法比html()方法更安全,无注入风险。
严格意义上,html()方法不符合CSP规范,直接将字符串解析为DOM节点
业务需要确实要使用.html()方法渲染动态内容时,必须做安全检查,避免恶意代码注入
.text()和.html()获取值可能存在代码缩进(空格和TAB),如有需要可以使用$.trim()来剔除
数组与对象深挖要点:
数组对象仅有concat/reverse/slice/splice为标准API,而且绝对完全兼容
数组对象请勿使用indexOf、lastIndexOf、map、every、forEach等非标准API,不仅兼容性存在问题,而且效率不一定高,反而不如自己实现
遍历数组请将.length缓存到变量
for(vari=0,l=arr.length;i遍历数组请勿使用此写法
for(vari in arr){...}遍历key-value型对象必须使用hasOwnProperty()来过滤遍历结果。
for(var key in obj) { if(!obj.hasOwnProperty(key) continue; //... }不论是数组或对象,在遍历操作时不要改变被遍历的变量结构,如增删元素,增删key值等(虽然你可以这么做),对于元素自身及子成员的修改是绝对安全的。
关于Prototype的使用要点:
不要乱用Prototype。不要轻易在Object/Array/Function等对象上追加prototype(虽然我们已有某些库这么做了)容易产生歧义冲突,在使用for~in遍历时很容易引发问题。
自定义的prototype成员会在for~in循环中出现,请根据实际情况使用hasOwnProperty()来过滤遍历结果。
不严谨的写法:
function Test() {} Test.prototype.a = 1; Test.prototype.b = 2; var o = new Test(); for(vari in o) { console.log({key: i, value: o}); } //{key:a, value:1} //{key:b, value:2} 严谨的写法: var o = new Test(); for(vari in o) { if(!o.hasOwnProperty(i)) continue; console.log({key: i, value: o}); } //无输出对象的__proto成员,用途是获取当前实例的原型对象。非标准实现,存在兼容性问题,请不要使用
原则上不要轻易重写已存在的prototype方法。但可以在单个实例中覆写该方法
prototype上定义静态对象变量,会造成所有对象共用,而不是分别创建实例,请在构造方法中分配实例
错误写法:
function Test() {} Test.prototype.arr = []; var a = new Test(); var b = new Test(); a.arr.push(1); b.arr.push(2); console.log(a.arr, b.arr); //[1,2], [1,2] 正确写法 function Test() { this.arr = []; } var a = new Test(); var b = new Test(); a.arr.push(1); b.arr.push(2); console.log(a.arr, b.arr); //[1], [2]总结JS是门灵活的语言,灵活到想怎么写都可以。但里面坑还是不少的。在有多种选择时,多考虑下哪种方法更好,而不是盲目选择一种。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/95778.html
摘要:续前文后端好书阅读与推荐,几十天过去了,又看了两本好书还有以前看过的书,这里依然把它们总结归纳一下,加入一些自己的看法有用的链接和可能的延伸阅读,并推荐给需要的同学。 续前文 后端好书阅读与推荐 - Mageek`s Wonderland ,几十天过去了,又看了两本好书(还有以前看过的书),这里依然把它们总结归纳一下,加入一些自己的看法、有用的链接和可能的延伸阅读,并推荐给需要的同学。...
摘要:续前文后端好书阅读与推荐,几十天过去了,又看了两本好书还有以前看过的书,这里依然把它们总结归纳一下,加入一些自己的看法有用的链接和可能的延伸阅读,并推荐给需要的同学。 续前文 后端好书阅读与推荐 - Mageek`s Wonderland ,几十天过去了,又看了两本好书(还有以前看过的书),这里依然把它们总结归纳一下,加入一些自己的看法、有用的链接和可能的延伸阅读,并推荐给需要的同学。...
阅读 2931·2021-11-24 10:22
阅读 3006·2021-11-23 10:10
阅读 1264·2021-09-28 09:35
阅读 1700·2019-08-29 13:16
阅读 1373·2019-08-26 13:29
阅读 2761·2019-08-26 10:27
阅读 659·2019-08-26 10:09
阅读 1414·2019-08-23 18:05