标签:lines 准备 tag 自己 获取 innerhtml pst 证明 理解
jq是模块化的,是一个以代码集合和功能为中心的模块
Sizzle 选择器引擎,非常常用的选择器引擎
jq 的整体结构:
(function( window, undefined ) {
//
})( window );
jQuery.extend = jQuery.fn.extend = function( obj ) {
for ( var k in obj ) {
this[ k ] = obj[ k ];
}
};
等价于
jQuery.extend = function( obj ) {
for ( var k in obj ) {
this[ k ] = obj[ k ];
}
};
jQuery.fn.extend = function( obj ) {
for ( var k in obj ) {
this[ k ] = obj[ k ];
}
};
给页面中 div 和 p 添加上边框
var divs = document.getElementsByTagName( ‘div‘ ); // HTMLCollection
var ps = document.getElementsByTagName( ‘p‘ );
// 由于 Collection 不是真的数组,也不允许使用 divs.push(...)
// 但是 Collection 也是不允许修改的 [].push.apply( divs, ps );
// 自己定义 一个数组
var arr = [];
arr.push.apply( arr, divs );
arr.push.apply( arr, ps );
arr.forEach( function( v, i ) {
v.style.border = ‘1px solid red‘;
});
封装简化
// 需要一个函数,带有两个参数第一个参数是元素的标签名,第二个参数是一个数组,
// 表示将本次获得的元素加到哪一个数组中
// getTag
function getTag( tagName, results ) {
var tags = document.getElementsByTagName( tagName );
results.push.apply(results, tags);
}
var arr = [];
getTag( ‘div‘, arr );
getTag( ‘p‘, arr );
arr.forEach( function( v, i ) {
v.style.border = ‘1px dotted red‘;
});
再一次封装简化
function getTag( tagName, results ) {
results = results || [];
var tags = document.getElementsByTagName( tagName );
results.push.apply( results, tags );
return results;
}
var arr = getTag( ‘div‘ );
arr = getTag( ‘p‘, arr );
arr.forEach( function( v, i ) {
v.style.border = ‘1px solid blue‘;
});
<div id="dv">div1</div>
<div>
div2
<p class="c">p1</p>
<p>p2</p>
<p class="c">p3</p>
<p>p4</p></div>
<div>div3</div>
<div class="c">div4</div>
<p>p4</p>
<p>p5</p>
<p>p6</p>
<p>p7</p>
var node1 = document.querySelectorAll( ‘#dv‘ );
var node2 = document.querySelectorAll( ‘p, div‘ );
var node3 = document.querySelectorAll( ‘.c‘ );
var node4 = document.querySelectorAll( ‘#p‘ );
var node5 = document.querySelectorAll( ‘div .c‘ );
封装一个 select
// 自己封装一个函数 select
function select( selector, results ) {
results = results || [];
var nodeList = document.querySelectorAll( selector );
results.push.apply( results, nodeList );
return results;
}
select( ‘div .c‘ ).forEach( function( v ) {
v.style.border = ‘1px solid blue‘;
});
function byId( idName, results ) {
// 获得的元素,返回
results = results || [];
var find = document.getElementById( idName ) ;
// 只有找到数据才会加入
if( find ) results.push( find );
return results;
}
// tag
function byTag( tagName, results ) {
results = results || [];
results.push.apply(results,document.getElementsByTagName( tagName ));
return results;
}
// byClass
function byClass( className, results ) {
results = results || [];
results.push.apply(results,document.getElementsByClassName( className ));
return results;
}
function byAll( results ) {
return byTag( ‘*‘, results );
}
而低版本浏览器是没有 getElementsByClassName 的,需要自己封装
<div class="c"></div>
<div class="c1 c2 c"></div>
<div class="c1 c c2"></div>
<div class="c1 c2"></div>
function getByClass( className ) {
// 首先获取页面中所有元素 然后再筛选出指定类名的
var list = document.getElementsByTagName( ‘*‘ );
var res = [];
for( var i = 0; i < list.length; i++ ) {
if( list[ i ].className == className ) {
res.push( list[ i ] );
}
}
return res;
}
要保证 class 属性中 有 c,那么 要么 c 在中间,两端有空格,例如:“c1 c c2”
要么,c 在两端,一边有空格,一边是引号, 例如:“c1 c” 或 “c c2”
首先判断 className 是否包含 c
然后再看 c 是否在 两端,indexOf,0,length - 1,即判断 1 或 length - 2 是否为空格
如果在中间,那么就看两端是否为空格 i - 1 和 i + 1
正则表达式:
c 在中间或两端
/^\sc\s|\sc\s|\sc$|^c$/g
function contains( str1, str2 ) {
// 利用字符串拼接得到正则式
return ( /^c\s|\sc\s|\sc$/g ).test( str1 );
var regexpStr = "^\\s" + str2 + "\\s|\\s" + str2 + "\\s|\\s" + str2 + "$";
return ( new RegExp( regexpStr, ‘g‘ ) ).test( str1 );
}
// 改良 getByClass
function getByClass( className ) {
// 首先获取页面中的所有元素, 然后在筛选出 指定类名的
var list = document.getElementsByTagName( ‘*‘ );
var res = [];
for ( var i = 0; i < list.length; i++ ) {
if ( list[ i ].className == className || contains( list[ i ].className, className ) ) {
res.push( list[ i ] );
}
}
return res;
}
console.log(getByClass(‘c‘));
console.log(getByClass(‘c1‘));
jquery 作者的实现方法
// jq 作者的实现方法
function getByClass ( className ) {
var list = document.getElementsByTagName( ‘*‘ );
var res = [];
for ( var i = 0; i < list.length; i++ ) {
// 目的是在 list[ i ].className 中 看是否有 className
if ( ( " " + list[ i ].className + " " ).indexOf( " " + className + " " ) > -1 ) {
res.push( list[ i ] );
}
}
return res;
}
// c " c " " c " 0
// c1 c2 c " c1 c2 c " " c " 6
// c1 c c2 " c1 c c2 " " c " 3
// c1 c2 " c1 c2 " " c "
var list = getByClass( ‘c‘ );
document.getElementsByClassName
str.indexOf
arr.filter
...
低版本的浏览器可能不支持
一般由两种主流的实现方法
第一种方法:检查系统是否提供,如果没有则自己加入,并不推荐,因为修改了 document 对象,污染了 document 对象
if ( !document.getElementsByClassName ) {
// 进入该范围表示: get*byClassName 不存在
// 进入兼容区域
document.getElementsByClassName = function ( className ) {
var list = document.getElementsByTagName( ‘*‘ );
var res = [];
for ( var i = 0; i < list.length; i++ ) {
if ( ( " " + list[ i ].className + " " ).indexOf( " " + className + " " ) > -1 ) {
res.push( list[ i ] );
}
}
return res;
};
}
第二种方法:重新定义一个替代性方法(函数),在方法中判断系统是否支持,如果支持,就直接使用,如果不支持则自己实现算法,注意,不是修改 document 对象
function getByClass(className) {
// 检查系统是否支持该方法, 如果支持就直接使用
// 如果不持之在自己实现算法完成. 注意, 不是修改 document 对象
if (document.getElementsByClassName) {
return document.getElementsByClassName(className);
} else {
var list = document.getElementsByTagName(‘*‘), res = [];
for (var i = 0; i < list.length; i++) {
if (( " " + list[i].className + " " ).indexOf(" " + className + " ") > -1) {
res.push(list[i]);
}
}
return res;
}
}
第二种方法实现需要考虑一些细节
在框架被一加载的时候, 就完成判断, 是否存在存在一个变量中, 每次再判断的时候, 直接判断变量, 这里用了能力检测 => 对方法的定义进行检查
var support = {};
var rnative = /\{\s*\[native/;
support.getElementsByClassName = rnative.test(document.getElementsByClassName + ‘‘);
function getByClassName(className, node) {
node = node || document;
var list, res = [], i;
if (support.getElementsByClassName) {
return node.getElementsByClassName(className);
} else {
list = document.getElementsByTagName(‘*‘);
for (i = 0; i < list.length; i++) {
if (( " " + list[i].className + " " ).indexOf(" " + className + " ") > -1) {
res.push(list[i]);
}
}
return res;
}
}
一般提供一个对象, support, 里面有很多属性,属性名与方法名相同, 但是其值 为 bool 值 表示该方法是否可用。
var support = {
qsa:true,
getElementsByClassName: false
}
var support = {};
// 以 getElementsByClassName 为例
support.getElementsByClassName = (function () {
var div = document.createElement(‘div‘);
// 验证该方法是否可用
if (typeof div.getElementsByClassName === ‘function‘) {
// 证明他是一个方法
div.innerHTML = ‘<div class="c"></div>‘; // 准备一个 标签结构
var res = div.getElementsByClassName(‘c‘); // 调用方法以后, 看是否可以完成要的功能
if (res && res.length === 1 && res[0].className === ‘c‘) {
return true;
}
}
return false;
})();
alert( document.getElementsByClassName );
document.getElementsByClassName = function ( selector ) {
return 123;
};
alert( document.getElementsByClassName );
// 内置的方法都会返回 function 函数名 () { [native code] }
// 一旦方法存在, 并且方法的实现都是 [native ... ] 那么就可以肯定, 方法可用
所以对方法的定义进行检测, 检查方法是不是系统实现的,内置的方法都会返回 function 函数名 () { [native code] },他是不可修改的,且是不可见的
var support = {};
support.getElementsByClassName = (function () {
var str = document.getElementsByClassName + ‘‘;
var rnative = /\{\s*\[native/;
return rnative.test(str);
})();
alert(support.getElementsByClassName); // IE 8 false / chrome True
标签:lines 准备 tag 自己 获取 innerhtml pst 证明 理解
原文地址:http://blog.csdn.net/qq_16415157/article/details/53727714