浅析JavaScript中浏览器的兼容问题


Posted in Javascript onApril 19, 2016

浏览器兼容性问题是在实际开发中容易忽略而又最重要的一部分。我们在讲老版本浏览器兼容问题之前,首先要了解什么是能力检测,它是来检测浏览器有没有这种能力,即判断当前浏览器是否支持要调用的属性或者方法。下面做了一些简短的介绍。

1、innerText 和 innerContent
1)innerText 和 innerContent 的作用相同
2)innerText IE8之前的浏览器支持
3)innerContent 老版本的Firefox支持
4)新版本的浏览器两种方式都支持

1 // 老版本浏览器兼容 innerText 和 innerContent
2 if (element.textContent) {
3    return element.textContent ;
4  } else {
5    return element.innerText;
6  }

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();

【总结】这里只是做了一部分的小结,实际开发中也还会遇到各种浏览器兼容的问题。不同浏览器在PC端和手机端也会遇到不同适配问题,这些就有待童鞋们一起去发掘总结啦~~希望能帮到大家,不足的地方请多指教啦~~~

以上这篇浅析JavaScript中浏览器的兼容问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery制作弹窗提示窗口代码分享
Mar 02 Javascript
js简单抽奖代码
Jan 16 Javascript
javascript加减乘除的简单实例
Jul 12 Javascript
用JS写的一个Ajax库(实例代码)
Aug 06 Javascript
基于JS实现发送短信验证码后的倒计时功能(无视页面刷新,页面关闭不进行倒计时功能)
Sep 02 Javascript
React-Native实现ListView组件之上拉刷新实例(iOS和Android通用)
Jul 11 Javascript
Node.JS中快速扫描端口并发现局域网内的Web服务器地址(80)
Sep 18 Javascript
Postman模拟发送带token的请求方法
Mar 31 Javascript
ES6使用export和import实现模块化的方法
Sep 10 Javascript
详解js实时获取并显示当前时间的方法
May 10 Javascript
js 计算月/周的第一天和最后一天代码
Feb 01 Javascript
js canvas实现五子棋小游戏
Jan 22 Javascript
javascript+HTML5 Canvas绘制转盘抽奖
May 16 #Javascript
深入浅析JavaScript中的constructor
Apr 19 #Javascript
js点击返回跳转到指定页面实现过程
Aug 20 #Javascript
javascript html5摇一摇功能的实现
Apr 19 #Javascript
一些实用性较高的js方法
Apr 19 #Javascript
jQuery移动端日期(datedropper)和时间(timedropper)选择器附源码下载
Apr 19 #Javascript
JavaScript中创建对象的模式汇总
Apr 19 #Javascript
You might like
smarty 原来也不过如此~~呵呵
2006/11/25 PHP
收藏的PHP常用函数 推荐收藏保存
2010/02/21 PHP
PHP下利用header()函数设置浏览器缓存的代码
2010/09/01 PHP
解析PHP中常见的mongodb查询操作
2013/06/20 PHP
ThinkPHP实现带验证码的文件上传功能实例
2014/11/01 PHP
php下载远程大文件(获取远程文件大小)的实例
2017/06/17 PHP
ExtJs 3.1 XmlTreeLoader Example Error
2010/02/09 Javascript
jquery选择checked在ie8普通模式下的问题
2014/02/12 Javascript
jquery序列化方法实例分析
2015/06/10 Javascript
轻松学习Javascript闭包函数
2015/12/15 Javascript
多种js图片预加载实现方式分享
2016/02/19 Javascript
js获取iframe中的window对象的实现方法
2016/05/20 Javascript
JS查找孩子节点简单示例
2019/07/25 Javascript
vue项目中自定义video视频控制条的实现代码
2020/04/26 Javascript
Layui弹框中数据表格中可双击选择一条数据的实现
2020/05/06 Javascript
Nuxt默认模板、默认布局和自定义错误页面的实现
2020/05/11 Javascript
jQuery HTML获取内容和属性操作实例分析
2020/05/20 jQuery
JavaScript实现HSL拾色器
2020/05/21 Javascript
[50:58]2018DOTA2亚洲邀请赛3月29日 小组赛A组OpTic VS Newbee
2018/03/30 DOTA
[05:20]2018DOTA2亚洲邀请赛主赛事第三日战况回顾 LGD率先挺进胜者组决赛
2018/04/06 DOTA
python中将字典形式的数据循环插入Excel
2018/01/16 Python
Flask核心机制之上下文源码剖析
2018/12/25 Python
用python 实现在不确定行数情况下多行输入方法
2019/01/28 Python
关于pytorch多GPU训练实例与性能对比分析
2019/08/19 Python
python实现的Iou与Giou代码
2020/01/18 Python
Coggles美国/加拿大:高级国际时装零售商
2018/10/23 全球购物
英国最大的独立玩具专卖店:The Entertainer
2019/09/06 全球购物
高三自我鉴定范文
2013/10/19 职场文书
费用会计岗位职责
2014/01/01 职场文书
女儿十岁生日答谢词
2014/01/27 职场文书
有关九一八事变的演讲稿
2014/09/14 职场文书
2014年维稳工作总结
2014/11/18 职场文书
2015年个人招商工作总结
2015/04/25 职场文书
2015年计划生育责任书
2015/05/08 职场文书
2016新教师培训心得体会范文
2016/01/08 职场文书
PHP使用QR Code生成二维码实例
2021/07/07 PHP