问题分析:例如在IE8浏览器及以下,不兼容getElementsByClassName,那么问题1是如何判断浏览器是否支持,问题2是如何实现自己的方法
-
首先拿到这个问题,一般想到的是用if判断条件,如下
if(node.getElementsByClassName){ return node.getElementsByClassName(className); }else{ //其他方法 }
上述方法每调用一次,浏览器都会进行一次判断,随着代码和框架的增多,那么浏览器的性能会严重损耗,那么如何处理以上问题呢?
-
对于上述问题进行分析,我们试着可以在js加载开始的时候就进行能力判断,判断属性方法是否存在,存储布尔值真和假
实现逻辑:
在全局作用域中( 最终都要变成沙箱 )提供一个 support对象,里面提供所有的与方法名相同的属性, 值均为 boolean, 那么凡是涉及到 能力检查的时候 就直接使用 support 即可
var support = {}; support.getElementsByClassName = !!document.getElementsByClassName; if ( support.getElementsByClassName ) { // return node.getElementsByClassName( className ); alert('支持该方法'); } else { // 自己实现( className ); alert('不支持该方法'); }
-
拓展:以上方法实现了是否存在该方法和属性,那么现在需求是不仅判断其是否存在,还要判断是否符合要求
var support = {}; support.getElementsByClassName = (function () { var isExist = !!document.getElementsByClassName; //判断是否存在,并且它还是一个方法 if ( isExist && typeof document.getElementsByClassName == 'function' ) { // 自己创建一些元素, 并且加上 class 属性, 看是否可以获得到加上的所有元素(假设其他方法都是存在的) var div = document.createElement( 'div' ), divClass = document.createElement( 'div' ); divClass.className = 'cn'; div.appendChild( divClass ); var bool = div.getElementsByClassName( 'cn' )[ 0 ] === divClass; return bool; } return false;//如果不满足 })();
判断返回的布尔值,应用上面方法
if ( support.getElementsByClassName ) { // return node.getElementsByClassName( className ); alert( '支持该方法' ); } else { // 自己实现( className ); alert( '不支持该方法' ); }
-
最后getClass方法完整实现
var getClass = function ( className, results ) { results = results || []; var tempArr, i; // 首先判断系统所提供的方法是否可以实现该功能 if ( document.getElementsByClassName ) { results.push.apply( results, document.getElementsByClassName( className ) ); } else { // 思路: 首先获得所有元素, 然后在元素中搜索符合要求的, 再加入到数组中 tempArr = document.getElementsByTagName( '*' ); // for 循环, 判断是否符合要求 for ( i = 0; i < tempArr.length; i++ ) { // tempArr[ i ].className === className // 多个样式是处理不了的 // tempArr[ i ].className.indexOf( className ) != -1 // 判断查找类样式是否存在得到下面做法,在每个类上加上空格,确保每个类都能被查找到 // 在这暂时考虑兼容 className 或 getAttribute if ( ( ' ' + tempArr[ i ].className + ' ' ) .indexOf( ' ' + className + ' ' ) != -1 ) { results.push( tempArr[ i ] ); } } } return results; };
验证上面的getClass方法
<html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> div { 400px; height: 50px; margin: 10px 0; } .c1 { border: 1px solid green; } .c2 { border: 1px solid blue; } </style> </head> <body> <div class="c1"></div> <div class="c2"></div> <div class="c2"></div> <div class="c1"></div> </body> </html> <script> var list = getClass( 'c2' ); for ( var k in list ) { list[ k ].style.backgroundColor = 'skyblue'; } </script>