浅析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 相关文章推荐
JavaScript高级程序设计 学习笔记 js高级技巧
Sep 20 Javascript
html5 canvas js(数字时钟)实例代码
Dec 23 Javascript
javascript获得当前的信息的一些常用命令
Feb 25 Javascript
JavaScript原生对象之Number对象的属性和方法详解
Mar 13 Javascript
jQuery树形插件jquery.simpleTree.js用法分析
Sep 05 Javascript
jQuery插入节点和移动节点用法示例(insertAfter、insertBefore方法)
Sep 08 Javascript
angular框架实现全选与单选chekbox的自定义
Jul 06 Javascript
JS实现页面打印(整体、局部)
Aug 18 Javascript
JavaScript类的继承方法小结【组合继承分析】
Jul 11 Javascript
监控微信小程序中的慢HTTP请求过程详解
Jul 05 Javascript
JavaScript数组及常见操作方法小结
Nov 13 Javascript
JS实现页面炫酷的时钟特效示例
Aug 14 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
几款免费开源的不用数据库的php的cms
2010/12/19 PHP
PHP+JS+rsa数据加密传输实现代码
2011/03/23 PHP
php发送post请求的三种方法
2014/02/11 PHP
php获取客户端电脑屏幕参数的方法
2015/01/09 PHP
php删除指定目录的方法
2015/04/03 PHP
使用JavaScript创建新样式表和新样式规则
2016/06/14 PHP
windows下的WAMP环境搭建图文教程(推荐)
2017/07/27 PHP
PHP获取本周所有日期或者最近七天所有日期的方法
2018/06/20 PHP
用ADODB.Stream转换
2007/01/22 Javascript
JS控制阿拉伯数字转为中文大写示例代码
2013/09/04 Javascript
用Jquery.load载入页面实现局部刷新
2014/01/22 Javascript
Javascript中3种实现继承的方法和代码实例
2014/08/12 Javascript
jQuery实现的tab标签切换效果示例
2016/09/05 Javascript
基于JS组件实现拖动滑块验证功能(代码分享)
2016/11/18 Javascript
微信公众平台开发教程(六)获取个性二维码的实例
2016/12/02 Javascript
ES6数组的扩展详解
2017/04/25 Javascript
swiper自定义分页器使用方法详解
2020/09/14 Javascript
vue 全选与反选的实现方法(无Bug 新手看过来)
2018/02/09 Javascript
详解Vue webapp项目通过HBulider打包原生APP
2018/06/29 Javascript
bootstrap-table实现表头固定以及列固定的方法示例
2019/03/07 Javascript
js的Object.assign用法示例分析
2020/03/05 Javascript
Node.js API详解之 Error模块用法实例分析
2020/05/14 Javascript
[18:32]DOTA2 HEROS教学视频教你分分钟做大人-谜团
2014/06/12 DOTA
python实现SMTP邮件发送功能
2020/06/16 Python
Python3.6.0+opencv3.3.0人脸检测示例
2018/05/25 Python
Python使用mongodb保存爬取豆瓣电影的数据过程解析
2019/08/14 Python
python类中super() 的使用解析
2019/12/19 Python
python实现银行实战系统
2020/02/26 Python
移动端rem布局的两种实现方法
2018/01/03 HTML / CSS
HTML5实现动画效果的方式汇总
2016/02/29 HTML / CSS
大学生实习感言
2014/01/16 职场文书
个人安全承诺书
2014/05/22 职场文书
房屋租房协议书范本
2014/12/04 职场文书
2014年幼儿园老师工作总结
2014/12/05 职场文书
2015年环卫处个人工作总结
2015/07/27 职场文书
使用pandas生成/读取csv文件的方法实例
2021/07/09 Python