javascript 兼容总结
1 大多数兼容性问题可通过 if(){…}else{…} 来解决 2 this 的指向问题 3 1)构造函数中的 this 指 “.”前的对象 4 2)new 出来的对象,this 指当前对象 5 3)回调函数中的 this 指 window 6 4)给当前元素添加事件 this 指当前元素 7 8 JS中出现的兼容性问题的总结 9 1.关于获取行外样式 currentStyle 和 getComputedStyle 出现的兼容性问题 10 我们都知道js通过style不可以获取行外样式,当我们需要获取行外样式时: 11 我们一般通过这两个方法获取行外样式: 12 IE下: currentStyle 13 Chrome,FF下: getComputedStyle(oDiv,false) 14 兼容两个浏览器的写法: 15 if(oDiv.currentStyle){ 16 alert(oDiv.currentStyle.width); 17 }else{ 18 alert(getComputedStyle(oDiv,false).width); 19 } 20 *注:在解决很多兼容性写法时,都是用if..else.. 21 22 封装一个获取行外样式的函数:(兼容所有浏览器,包括低版本IE6,7) 23 funtion getStyle(obj,name){ 24 if(obj.currentStyle){ 25 //IE 26 return obj.currentStyle[name]; 27 }else{ 28 //Chrom,FF 29 return getComputedStyle(obj,false)[name]; 30 } 31 } 32 调用:getStyle(oDiv,'width'); 33 34 2.关于用“索引”获取字符串每一项出现的兼容性问题: 35 对于字符串也有类似于 数组 这样的通过 下标索引 获取每一项的值, 36 var str="abcde"; 37 aletr(str[1]); 38 但是低版本的浏览器IE6,7不兼容 39 兼容方法:str.charAt(i) //全部浏览器都兼容 40 var str="abcde"; 41 for(var i=0;i<str.length;i++){ 42 alert(str.charAt(i)); //返回字符串中的每一项 43 } 44 45 3.关于DOM中 childNodes 获取子节点出现的兼容性问题 46 childNodes:获取子节点, 47 --IE6-8:获取的是元素节点,正常 48 --高版本浏览器:但是会包含文本节点和元素节点(不正常) 49 解决方法: 使用nodeType:节点的类型,并作出判断 50 --nodeType=3-->文本节点 51 --nodeType=1-->元素节点 52 例: 获取ul里所有的子节点,让所有的子节点背景色变成红色 53 获取元素子节点兼容的方法: 54 var oUl=document.getElementById('ul'); 55 for(var i=0;i<oUl.childNodes.length;i++){ 56 if(oUl.childNodes[i].nodeType==1){ 57 oUl.childNodes[i].style.background='red'; 58 } 59 } 60 注:上面childNodes为我们带来的困扰完全可以有children属性来代替。 61 children属性:只获取元素节点,不获取文本节点,兼容所有的浏览器, 62 比上面的好用所以我们一般获取子节点时,最好用children属性。 63 var oUl=document.getElementById('ul'); 64 oUl.children.style.background="red"; 65 66 4.关于使用 firstChild,lastChild 等,获取第一个/最后一个元素节点时产生的问题 67 --IE6-8下: firstChild,lastChild,nextSibling,previousSibling,获取第一个元素节点 68 (高版本浏览器IE9+,FF,Chrome不兼容,其获取的空白文本节点) 69 --高版本浏览器下: firstElementChild,lastElementChild,nextElementSibling,previousElementSibling 70 (低版本浏览器IE6-8不兼容) 71 --兼容写法: 找到ul的第一个元素节点,并将其背景色变成红色 72 var oUl=document.getElementById('ul'); 73 if(oUl.firstElementChild){ 74 //高版本浏览器 75 oUl.firstElementChild.style.background='red'; 76 }else{ 77 //IE6-8 78 oUl.firstChild.style.background='red'; 79 } 80 81 5.关于使用 event对象,出现的兼容性问题 82 如: 获取鼠标位置 83 IE/Chrom: event.clientX;event.clientY 84 FF/IE9以上/Chrom: 传参ev--> ev.clientX;ev.clientY 85 获取event对象兼容性写法: var oEvent==ev||event; 86 document.oncilck=function(ev){ 87 var oEvent==ev||event; 88 if(oEvent){ 89 alert(oEvent.clientX); 90 } 91 } 92 93 6.关于为一个元素绑定两个相同事件:attachEvent/attachEventLister 出现的兼容问题 94 事件绑定:(不兼容需要两个结合做兼容if..else..) 95 IE8以下用: attachEvent('事件名',fn); 96 FF,Chrome,IE9-10用: attachEventLister('事件名',fn,false); 97 多事件绑定封装成一个兼容函数: 98 function myAddEvent(obj,ev,fn){ 99 if(obj.attachEvent){ 100 //IE8以下 101 obj.attachEvent('on'+ev,fn); 102 }else{ 103 //FF,Chrome,IE9-10 104 obj.attachEventLister(ev,fn,false); 105 } 106 } 107 myAddEvent(oBtn,'click',function(){ 108 alert(a); 109 }); 110 myAddEvent(oBtn,'click',function(){ 111 alert(b); 112 }); 113 114 7.关于获取滚动条距离而出现的问题 115 当我们获取滚动条滚动距离时: 116 IE,Chrome: document.body.scrollTop 117 FF: document.documentElement.scrollTop 118 兼容处理:var scrollTop=document.documentElement.scrollTop||document.body.scrollTop
/*****************************************补充内容****************************************/
1、innerText和innerContent
1)innerText和innerContent的作用相同
2)innerText IE8之前的浏览器支持
3)innerContent 老版本的Firefox支持
4)新版本的浏览器两种方式都支持
// 老版本浏览器兼容 innerText 和 innerContent
if(ele.textContent){
return ele.textContent;
}else{
return ele.innerText;
}
2、获取兄弟节点/元素的兼容性问题
1)兄弟节点,所有浏览器都支持
①nextSibling 下一个兄弟节点,可能是非元素节点;会获取到文本节点
②previousSibling 上一个兄弟节点,可能是非元素节点;会获取到文本节点
2)兄弟元素,IE8以前不支持
①previousElementSibling 获取上一个紧邻的兄弟元素,会忽略空白
②nextElementSibling 获取下一个紧邻的兄弟元素,会忽略空白
//兼容浏览器
// 获取下一个紧邻的兄弟元素
function
getNextElement(element) {
// 能力检测
if
(element.nextElementSibling) {
return
element.nextElementSibling;
}
else
{
var
node = element.nextSibling;
while
(node && node.nodeType !== 1) {
node = node.nextibling;
}
return
node;
}
}
/**
* 返回上一个元素
* @param element
* @returns {*}
*/
function
getPreviousElement(element) {
if
(element.previousElementSibling) {
return
element.previousElementSibling;
}
else
{
var
el = element.previousSibling;
while
(el && el.nodeType !== 1) {
el = el.previousSibling;
}
return
el;
}
}
/**
* 返回第一个元素firstElementChild的浏览器兼容
* @param parent
* @returns {*}
*/
function
getFirstElement(parent) {
if
(parent.firstElementChild) {
return
parent.firstElementChild;
}
else
{
var
el = parent.firstChild;
while
(el && el.nodeType !== 1) {
el = el.nextSibling;
}
return
el;
}
}
/**
* 返回最后一个元素
* @param parent
* @returns {*}
*/
function
getLastElement(parent) {
if
(parent.lastElementChild) {
return
parent.lastElementChild;
}
else
{
var
el = parent.lastChild;
while
(el && el.nodeType !== 1) {
el = el.previousSibling;
}
return
el;
}
}
/**
*获取当前元素的所有兄弟元素
* @param element
* @returns {Array}
*/
function
sibling(element) {
if
(!element)
return
;
var
elements = [ ];
var
el = element.previousSibling;
while
(el) {
if
(el.nodeType === 1) {
elements.push(el);
}
el = el.previousSibling;
}
el = element.previousSibling;
while
(el ) {
if
(el.nodeType === 1) {
elements.push(el);
}
el = el.nextSibling;
}
return
elements;
}
3、array.filter();
// 使用指定的函数测试所有元素,并创建一个包含所有通过测试的元素的新数组
// 兼容旧环境
if
(!Array.prototype.filter)
{
Array.prototype.filter =
function
(fun
/*, thisArg */
)
{
"use strict"
;
if
(
this
=== void 0 ||
this
===
null
)
throw
new
TypeError();
var
t = Object(
this
);
var
len = t.length >>> 0;
if
(
typeof
fun !==
"function"
)
throw
new
TypeError();
var
res = [];
var
thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for
(
var
i = 0; i < len; i++)
{
if
(i
in
t)
{
var
val = t[i];
// NOTE: Technically this should Object.defineProperty at
// the next index, as push can be affected by
// properties on Object.prototype and Array.prototype.
// But that method's new, and collisions should be
// rare, so use the more-compatible alternative.
if
(fun.call(thisArg, val, i, t))
res.push(val);
}
}
return
res;
};
}
4、array.forEach();
// 遍历数组
//兼容旧环境
// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
if
(!Array.prototype.forEach) {
Array.prototype.forEach =
function
(callback, thisArg) {
var
T, k;
if
(
this
==
null
) {
throw
new
TypeError(
' this is null or not defined'
);
}
// 1. Let O be the result of calling toObject() passing the
// |this| value as the argument.
var
O = Object(
this
);
// 2. Let lenValue be the result of calling the Get() internal
// method of O with the argument "length".
// 3. Let len be toUint32(lenValue).
var
len = O.length >>> 0;
// 4. If isCallable(callback) is false, throw a TypeError
exception.
// See: http://es5.github.com/#x9.11
if
(
typeof
callback !==
"function"
) {
throw
new
TypeError(callback +
' is not a function'
);
}
// 5. If thisArg was supplied, let T be thisArg; else let
// T be undefined.
if
(arguments.length > 1) {
T = thisArg;
}
// 6. Let k be 0
k = 0;
// 7. Repeat, while k < len
while
(k < len) {
var
kValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty
// internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if
(k
in
O) {
// i. Let kValue be the result of calling the Get internal
// method of O with argument Pk.
kValue = O[k];
// ii. Call the Call internal method of callback with T as
// the this value and argument list containing kValue, k, and O.
callback.call(T, kValue, k, O);
}
// d. Increase k by 1.
k++;
}
// 8. return undefined
};
}
5、注册事件
.addEventListener = function (type,listener,useCapture ) { };
//第一个参数 事件名称
//第二个参数 事件处理函数(监听者)
//第三个参数 true捕获 false冒泡
//IE9以后才支持
// 兼容旧环境
var
EventTools = {
addEventListener:
function
(element, eventName, listener) {
//能力检测
if
(element.addEventListener) {
element.addEventListener(eventName, listener,
false
);
}
else
if
(element.attachEvent) {
element.attachEvent(
"on"
+ eventName, listener);
}
else
{
element[
"on"
+ eventName] = listener;
}
},
// 想要移除事件,不能使用匿名函数
removeEventListener:
function
(element, eventName, listener) {
if
(element.removeEventListener) {
element.removeEventListener(eventName,listener,
false
);
}
else
if
(element.detachEvent) {
//IE8以前注册.attachEvent和移除事件.detachEvent
element.detachEvent(
"on"
+eventName,listener);
}
else
{
element[
"on"
+ eventName] =
null
;
}
}
};
6、事件对象
1)事件参数e,就是事件对象,标准的获取方式
btn.onclick = function(e) { }
2)e.eventPhase 事件阶段,IE8以前不支持
3)e.target 始终是触发事件的对象(点击的按钮)
i)IE8以前 srcElement
ii)浏览器兼容
var target = e.target || window.event.srcElement;
// 获取事件对象 兼容浏览器
getEvent:
function
(e) {
return
e || window.event;
// e事件对象 标准的获取方式; window.event IE8以前获取事件对象的方式
}
// 兼容target
getTarget:
function
(e) {
return
e.target || e.srcElement;
}
7、获取鼠标在页面上的位置
①在可视区域中的位置: e.clientX e.clientY
②在文档中的位置:
i) e.pageX e.pageY
ii)浏览器兼容
var
scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var
pageY = e.clientY + scrollTop;
8、获取页面滚动的距离
// 兼容浏览器
var
scrollTop = document.documentElement.scrollTop || document.body.scrolltop;
9、取消文本的选择
// 兼容浏览器
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();