js与jquery常用数组方法总结
昨天被问数组方法的时候,问到sort()方法是否会改变原来的数组。本来我猜是不会,也是这么说,马上我又觉得,知识这种东西,不确定的时候直接说不确定或不知道就好,只是凭借着不确定的猜测或者是记忆,害人害己,于是我又回答不知道。结果果然。。。我记错了0.0 还是自己总结测试一下比较靠谱,印象也比较深刻。欢迎大家提出相关意见或建议,提前谢谢哈~
一.原生js方法
1.遍历数组 in(同时也是对象遍历属性的方法)
var a = [1, 2, 3];
for (x in a) {
console.log(x);
}
2.合并数组 concat
var a = [1, 2, 3],
b = [4, 5, 6],
c;
c = b.concat(a); //将a加在b上,返回新数组,a和b并没有变。参数数量不限
console.log(b);
console.log(c);
3.合并数组的值为字符串 join
var a = [1, 2, 3],
b = a.join('*'); //默认为之间加上 ,
console.log(a); //a并没有变
console.log(b);
参数为分隔符,默认为" , "分隔,当参数为' '时表示直接连接,常用于js中拼接html,如自定义弹窗,js生成form表单。
4.数组排序 sort
var a = [6, 2, 3, 'a', 'x', 20],
b = a.sort(); //ASC表顺序,先看首位,因此20排在3前面
console.log(a); //a变化了
console.log(b);
a.push('k');
console.log(b); //a和b指向同一个对象,b相当于a的别名
可以在参数里写排序规则函数, 如全是数字从小到大排序(注意返回值正负)
var a = [3, 2, 6, 20],
b = a.sort(function(x, y) {
return x - y;
});
console.log(b);
当不全是数字的时候,会产生奇葩错误(NaN),见下图


由此可知,注意运算符的正确用法还是很重要的。对于NaN,能少操作就少操作,毕竟是唯一一个js中不等于任何值的类型(Not a Number),包括它本身(可以用来判断一个变量是不是NaN,未初始化的变量是无类型的)。
5.数组的模拟栈(FILO) 和队列(FIFO) 方法(均改变原来数组)

var a = [6, 2, 3, 'a', 'x', 20],
b = a.push('ab'), //末尾添加元素,并返回新长度
c = a.pop(), //删除并返回数组的最后一个元素
d = a.unshift('xy'), //开头添加元素,并返回新长度
e = a.shift(); //删除并返回数组的第一个元素
console.log(a);
console.log(b);
console.log(c);
console.log(d);
console.log(e);

可见这类方法添加元素则返回添加后长度, 删除元素则返回被删的那个可怜家伙(同splice)。
6.数组反序 reverse
var a = [6, 2, 3, 'a', 'x', 20],
b = a.reverse(); //返回a的引用
console.log(a);
console.log(b);
7.取数组中需要的部分 slice
var a = [6, 2, 3, 'a', 'x', 20],
b = a.slice(0, 2); //下标从0取到2(不包括2),没有第二个参数则默认到末尾。第一个参数为负表示从末尾开始数。第一个参数小于第二个参数则为空。
console.log(a);
console.log(b); //b是a一部分的副本,a本身不变
8.修改数组 splice (既然是修改数组,肯定数组本身会变的啦)
var a = [1, 2, 3, 4],
b = a.splice(0, 2, 6);
console.log(a);
console.log(b); //b为被删掉的数组部分
a.splice(index, num, newItem1, newItem2...):index为开始选择的元素下标,num为接下来要删除元素的个数,newItem为接下来(在删完的地方)要添加的新元素(非必须)。这个方法用途最多,如
删除指定下标(2,也就是第三个)元素,此时不设置需要添加的newItem,而num设为1
var a = [1, 2, 3, 4],
b = a.splice(2, 1);
console.log(a);
console.log(b);
在任意位置添加任意多个元素(如在下标2后添加两个元素'7','8'),此时num设为0
var a = [1, 2, 3, 4],
b = a.splice(2, 0, 7,8);
console.log(a);
console.log(b); //没有删除,b返回[]
根据元素值删除元素(结合jquery)
var a=[1,2,3,4];
a.splice($.inArray(2,a),1);
console.log(a);
plus:数组也是特殊的对象(但是拥有自己的方法,一般用下标访问),因此同样也有对象的通用方法toString和valueOf
var a = [1, 2, [3,2], 4],
b = a.toString(); // 转化为字符串(不管有多少层)
console.log(a); //a本身不变
console.log(b);
var a = [1, 2, 4],
b = a.valueOf(); // 返回原始值(其实还是它本身。。。)
console.log(a); //a本身不变
console.log(b);
小结:综上所述,js数组的原生方法里面
修改自身的有: splice, pop, push, shift, unshift, sort, reverse
不修改自己身的: slice, concat, join
二.Jquery常用js方法
1.遍历
可以对所有的元素进行操作。如果想要满足条件退出,用return false( 绝大部分jquery方法都可以这么退出)。
$.each(arr, callback(key, val)); //可以链式调用,返回arr,为本身
var a = [1, 2, 3, 4];
$.each(a, function(key, val) { //以jQuery对象的方法调用,兼容性好;也可以用$(a)将a转化为jquery对象,然后以$(a).each(function(){})的形式调用,下面的方法同
console.log(a[key] + '下标为' + key + '值为' + val);
});

//对应源码(jquery1.11.0下面同)
// Execute a callback for every element in the matched set.
// (You can seed the arguments with an array of args, but this is
// only used internally.
each: function( obj, callback, args ) {
var value,
i = 0,
length = obj.length,
isArray = isArraylike( obj );
if ( args ) {
if ( isArray ) {
for ( ; i < length; i++ ) {
value = callback.apply( obj[ i ], args ); //第三个参数用于扩展obj元素的方法,一般不用
if ( value === false ) {
break;
}
}
} else {
for ( i in obj ) {
value = callback.apply( obj[ i ], args );
if ( value === false ) {
break;
}
}
}
// A special, fast, case for the most common use of each
} else {
if ( isArray ) {
for ( ; i < length; i++ ) {
value = callback.call( obj[ i ], i, obj[ i ] );
if ( value === false ) {
break;
}
}
} else {
for ( i in obj ) {
value = callback.call( obj[ i ], i, obj[ i ] );
if ( value === false ) {
break;
}
}
}
}
return obj;
}

2. 筛选
$.grep(arr, callback, invert)
invert为false表示对callback的筛选取反。 默认为true。

var a = [1, 2, 3, 4];
$.grep(a, function(val, key) { //不能链式调用,返回[],所以可以加上return实现链式,返回满足条件的副本
if (a[key] > 2) {
console.log(key);
}
return val;
});

常用做获取两个数组中相同(或不相同)的部分

var a= [1, 2, 3, 4],
b=[1,3,5,7];
$.grep(a,function(val,key){
if(b.indexOf(val)>=0){
return val;
}
},false);


//jquery源码
grep: function( elems, callback, invert ) {
var callbackInverse,
matches = [],
i = 0,
length = elems.length,
callbackExpect = !invert; // Go through the array, only saving the items
// that pass the validator function
for ( ; i < length; i++ ) {
callbackInverse = !callback( elems[ i ], i ); //如果callback没有设置return,那么返回undefined(!undefined还是undefined)
if ( callbackInverse !== callbackExpect ) {
matches.push( elems[ i ] ); //只添加满足条件的,内部实现为push方法
}
} return matches;
}

3.转换
$.map(arr,callback(key,val))

var a = [1, 2, 3, 4];
$.map(a, function(val, key) { //不能链式调用,返回[],同grep加上return即可放回副本
if (a[key] > 2) {
a[key]=val+1;
}
return val; //可以链式调用,返回处理后的数组(也可用于筛选)
});


// arg is for internal usage only
map: function( elems, callback, arg ) {
var value,
i = 0,
length = elems.length,
isArray = isArraylike( elems ),
ret = []; // Go through the array, translating each of the items to their new values
if ( isArray ) {
for ( ; i < length; i++ ) {
value = callback( elems[ i ], i, arg ); if ( value != null ) {
ret.push( value );
}
} // Go through every key on the object,
} else {
for ( i in elems ) {
value = callback( elems[ i ], i, arg ); //如果callback没有返回值,那么value就是undefined if ( value != null ) {
ret.push( value );
}
}
} // Flatten any nested arrays
return concat.apply( [], ret ); //如果callback没有返回值,那么value就是[]
}

背景标白的区域为与each方法不同的地方,可以简单的理解为返回对象是否是副本(map是副本),另外map是为数组或类数组对象量身定做的,而each可以应用于全部对象。
4.合并
$.merge(arr1,arr2) arr1后面加上arr2后返回arr1
var a=[1,2,3],
b=[4,5,6];
$.merge(a,b); //可以有多个参数(居然不报错!),但是第三个及以后的没用(test in FF and Chrome)

//jquery源码
merge: function( first, second ) {
var len = +second.length,
j = 0,
i = first.length; while ( j < len ) {
first[ i++ ] = second[ j++ ];
} // Support: IE<9
// Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
if ( len !== len ) {
while ( second[j] !== undefined ) {
first[ i++ ] = second[ j++ ];
}
} first.length = i; return first;
}

源码的第二行有个+,最开始我以为是显式声明非负值,后来看到了arraylike,于是测试了极端情况如下:

var ax;
ax.length //报错,type error
+ax.length //报错,type error var ab={}; //空对象作为类空数组对象
ab.length //undefined
+ab.length //NaN var ab=[];
ab.length //0
+ab.length //0 var ab=null;
ab.length //报错,type error
+ab.length //报错,type error

忽然觉得然并卵。。。好吧,也许是我计较太多。如果有谁看到有关的解释,麻烦留下言,谢谢~
5.过滤相同元素
$.unique(arr)//过滤Jquery对象数组中重复的元素(内部实现为===)(不同版本不一样,不要用)
var a = [ 1 , 1 , 2 , 3 , 7 , 4 , 5 , 5 , 6 , 6 ];
$.unique(a)
jquery1.11.0运行结果

jquery1.8.3运行结果

好神奇啊,有木有!看一下源码保险~

//jquery1.11.0
jQuery.unique = Sizzle.uniqueSort; Sizzle.uniqueSort = function( results ) {
var elem,
duplicates = [],
j = 0,
i = 0; // Unless we *know* we can detect duplicates, assume their presence
hasDuplicate = !support.detectDuplicates;
sortInput = !support.sortStable && results.slice( 0 );
results.sort( sortOrder ); if ( hasDuplicate ) {
while ( (elem = results[i++]) ) {
if ( elem === results[ i ] ) { //用===
j = duplicates.push( i );
}
}
while ( j-- ) {
results.splice( duplicates[ j ], 1 ); //用splice实现
}
} // Clear input after sorting to release objects
// See https://github.com/jquery/sizzle/pull/225
sortInput = null; return results;
};


//jquery1.8.3
jQuery.unique = Sizzle.uniqueSort; Sizzle.uniqueSort = function( results ) {
var elem,
duplicates = [],
i = 1,
j = 0; hasDuplicate = baseHasDuplicate;
results.sort( sortOrder ); if ( hasDuplicate ) {
for ( ; (elem = results[i]); i++ ) {
if ( elem === results[ i - 1 ] ) {
j = duplicates.push( i );
}
}
while ( j-- ) {
results.splice( duplicates[ j ], 1 );
}
} return results;
};

对应红色的字体为新增或者修改的,然而并看不出什么,调试一下进入,会发现问题居然在sortOrder上!坑啊!继续找~~~

//jquery1.11.0
//定义时
sortOrder = function(a, b) {
if (a === b) {
hasDuplicate = true;
}
return 0;
}; //setDocument里面
sortOrder = hasCompare ?
function(a, b) { // Flag for duplicate removal
if (a === b) {
hasDuplicate = true;
return 0;
} // Sort on method existence if only one input has compareDocumentPosition
var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
if (compare) {
return compare;
} // Calculate position if both inputs belong to the same document
compare = (a.ownerDocument || a) === (b.ownerDocument || b) ?
a.compareDocumentPosition(b) : // Otherwise we know they are disconnected
1; // Disconnected nodes
if (compare & 1 ||
(!support.sortDetached && b.compareDocumentPosition(a) === compare)) { // Choose the first element that is related to our preferred document
if (a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a)) {
return -1;
}
if (b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b)) {
return 1;
} // Maintain original order
return sortInput ?
(indexOf.call(sortInput, a) - indexOf.call(sortInput, b)) :
0;
} return compare & 4 ? -1 : 1;
} :
function(a, b) {
// Exit early if the nodes are identical
if (a === b) {
hasDuplicate = true;
return 0;
} var cur,
i = 0,
aup = a.parentNode,
bup = b.parentNode,
ap = [a],
bp = [b]; // Parentless nodes are either documents or disconnected
if (!aup || !bup) {
return a === doc ? -1 :
b === doc ? 1 :
aup ? -1 :
bup ? 1 :
sortInput ?
(indexOf.call(sortInput, a) - indexOf.call(sortInput, b)) :
0; // If the nodes are siblings, we can do a quick check
} else if (aup === bup) {
return siblingCheck(a, b);
} // Otherwise we need full lists of their ancestors for comparison
cur = a;
while ((cur = cur.parentNode)) {
ap.unshift(cur);
}
cur = b;
while ((cur = cur.parentNode)) {
bp.unshift(cur);
} // Walk down the tree looking for a discrepancy
while (ap[i] === bp[i]) {
i++;
} return i ?
// Do a sibling check if the nodes have a common ancestor
siblingCheck(ap[i], bp[i]) : // Otherwise nodes in our document sort first
ap[i] === preferredDoc ? -1 :
bp[i] === preferredDoc ? 1 :
0;
};


//jquery 1.8.3
sortOrder = docElem.compareDocumentPosition ?
function( a, b ) {
if ( a === b ) {
hasDuplicate = true;
return 0;
} return ( !a.compareDocumentPosition || !b.compareDocumentPosition ?
a.compareDocumentPosition :
a.compareDocumentPosition(b) & 4
) ? -1 : 1;
} :
function( a, b ) {
// The nodes are identical, we can exit early
if ( a === b ) {
hasDuplicate = true;
return 0; // Fallback to using sourceIndex (in IE) if it's available on both nodes
} else if ( a.sourceIndex && b.sourceIndex ) {
return a.sourceIndex - b.sourceIndex;
} var al, bl,
ap = [],
bp = [],
aup = a.parentNode,
bup = b.parentNode,
cur = aup; // If the nodes are siblings (or identical) we can do a quick check
if ( aup === bup ) {
return siblingCheck( a, b ); // If no parents were found then the nodes are disconnected
} else if ( !aup ) {
return -1; } else if ( !bup ) {
return 1;
} // Otherwise they're somewhere else in the tree so we need
// to build up a full list of the parentNodes for comparison
while ( cur ) {
ap.unshift( cur );
cur = cur.parentNode;
} cur = bup; while ( cur ) {
bp.unshift( cur );
cur = cur.parentNode;
} al = ap.length;
bl = bp.length; // Start walking down the tree looking for a discrepancy
for ( var i = 0; i < al && i < bl; i++ ) {
if ( ap[i] !== bp[i] ) {
return siblingCheck( ap[i], bp[i] );
}
} // We ended someplace up the tree so do a sibling check
return i === al ?
siblingCheck( a, bp[i], -1 ) :
siblingCheck( ap[i], b, 1 );
};

很多是不是?有木有觉得瞬间被我坑了?啊哈,其实只要继续调试的时候断点设置好,你就会发现~~~没有比这更坑的了!它们都是循环的!1.8.3里面就在第一个function里面转来转去,手都点酸了也没看到出来,1.11.0整体循环,有参数的个数那么多次。
最后的结论是:还是不要用这个不靠谱的函数了。如果需要类似的功能,用原生js手动写就好。同时说明了关注更新的重要性,不过程序猿也不一定有那么长的时间去关注每一次的更新,那么就一定要准确的了解自己手头的版本,最好是空闲时对用到的功能测试一下,看下源码,网上得来终觉浅啊~
6.判断
$.inArray(val,arr) 判断val是否在arr里面
var a = [1, 2, 3, 4];
$.inArray(2, a); //有的话返回下标,没有的话返回-1

//对应源码
inArray: function(elem, arr, i) {
var len; if (arr) {
if (indexOf) {
return indexOf.call(arr, elem, i); //实际实现
} len = arr.length;
i = i ? i < 0 ? Math.max(0, len + i) : i : 0; for (; i < len; i++) {
// Skip accessing in sparse arrays
if (i in arr && arr[i] === elem) { //一般尽可能用===而杜绝==可能带来的隐式转换
return i;
}
}
} return -1;
}

7.元素转数组
$.makeArray()将一个类数组对象转换为真正的数组对象。(所谓"类数组对象"就是一个常规的Object对象,但它和数组对象非常相似:具备length属性,并以0、1、2、3……等数字作为属性名。不过它毕竟不是数组,没有从数组的原型对象上继承下来的内置方法(例如:push()、 sort()等)。)
$.toArray()将所有DOM元素恢复成数组。(其实用选择器取的时候就是很自然的数组的形式)
这两个实际用得太少了就不具体分析了,知道有这玩意就行吧。
三.补充
1.清空数组
方法1:length设为0 (js身为弱变量类型语言的体现之一,array的length属性可写)(效率比较低)
方法2:直接指向[]的引用 (如闭包销毁指向null一样,垃圾回收会自动回收空间)(效率比较高)
2.兼容性
IE8下
$.inArray 代替 indexOf
$.grep代替Array.prototype.filter
3.注意事项
一般情况下用$.functionName(obj,callback)的形式调用jquery方法的兼容性比较好,比如我曾遇到IE8及以下不能识别$(dom).val().trim()的情况,显示trim is not a function,然而改为$.trim($(dom).val())就没问题。
前面那种情况实际是string调用trim方法(如果加上call或者apply注入trim方法可以过,但是必要嘛?),后面是jquery对象调用trim方法。
最后再啰嗦一句,欢迎大家的意见和建议,帮我纠错,共同进步,谢谢!
附:之前学习权威指南的笔记图

js与jquery常用数组方法总结的更多相关文章
- 迟早要知道的JS系列之常用数组方法
常用数组方法 一.不会改变原始数组的方法: 即访问方法,下面的这些方法绝对不会改变调用它们的对象的值,只会返回一个新的数组或者返回一个其它的期望值. 1. concat() ** 语法:** Java ...
- jQuery 常用核心方法
jQuery 常用核心方法 .each() 遍历一个jQuery对象,为每个匹配元素执行一个函数 $('p').each(function(idx,node){ $(node).text(idx + ...
- ES6新增的常用数组方法(forEach,map,filter,every,some)
ES6新增的常用数组方法 let arr = [1, 2, 3, 2, 1]; 一 forEach => 遍历数组 arr.forEach((v, i) => { console.log( ...
- 【JS】怎样用原生JS实现jQuery的ready方法
Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,只是与window.onload方法还是有差别的. 总的来说,window. ...
- js中常用数组方法concat join push pop slice splice shift
javascript给我们很多常用的 数组方法,极大方便了我们做程序.下面我们来介绍下常用的集中数组方法. 比如 concat() join() push() pop() unshift() shif ...
- jQuery常用工具方法
前面的话 jQuery提供一些与元素无关的工具方法,不必选中元素,就可以直接使用这些方法.如果理解原生javascript的继承原理,那么就能理解工具方法的实质.它是定义在jQuery构造函数上的方法 ...
- Jquery常用的方法总结
1.关于页面元素的引用通过jquery的$()引用元素包括通过id.class.元素名以及元素的层级关系及dom或者xpath条件等方法,且返回的对象为jquery对象(集合对象),不能直接调用dom ...
- jQuery常用属性方法大全 attr(),val()
@@@@属性篇: 写作本篇文章的意义:jQuery的教程千千万,却没有英文版的API讲的系统.到位,一些话用中文翻译过来味道就变了,所以我将英文版的API的一些常用的方法单独提出来放在这里,并用自己的 ...
- js和jQuery判断数组是否包含指定元素
最近遇见一些前台基础性问题,在这里笔者觉得有必要记录一下,为了以后自己查阅或者读者查看. 已知var arr = ['java','js','php','C++']; 问题:arr数组是否包含‘jav ...
随机推荐
- DCL单例模式
我们第一次写的单例模式是下面这样的: public class Singleton { private static Singleton instance = null; public static ...
- 【转】Java的接口和抽象类
对于面向对象编程来说,抽象是它的一大特征.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有很多相似的地方,又有很多不同的地方. 一.抽象类 在了解抽象类之前,先来了解一下抽象方 ...
- Laravel-Excel 导入 Excel 文件----为什么只获取到最后一行数据?
### 今天使用了Laravel-Excel 到类文件,想做一个excel 文件到导入和导出,但是看了 官方到文档示例,自己做了一下,发现 只取到到最后一行到数据, 有点摸不着头脑! 网上找了一下, ...
- [PHP]PDO各方法在发生MYSQL断开时的反应
1.mixed PDO::errorCode ( void ) 如果单独执行此语句,并不能判断此时MYSQL是否已断开,它返回最上一次对MYSQL操作的错误码 2.public array PDO:: ...
- VUE 多页面配置(一)
1. 概述 1.1 说明 项目开发过程中会遇到需要多个主页展示情况,故在vue单页面的基础上进行配置多页面开发以满足此需求. 2. 实例 2.1 页面配置 2.1.1 默认首页 使用vue脚手架搭建后 ...
- Js操作Array数组
之前写过一篇文章,但是很模糊,不过却给我提供了一个思路,所以没有删除,这次写的是一个完善版本! 因为在很多的时候我们在选中了几行数据,然后存放在Array中,如下图: 看下控制台的数据 我双击了这两个 ...
- 12c rac On redhat 7
1 准备工作 1.1 关于GRID的一些变化 1.1.1 简化的基于映像的Oracle Grid Infrastructure安装 从Oracle Grid Infrastructure 12 ...
- 大数据mapreduce全局排序top-N之python实现
a.txt.b.txt文件如下: a.txt hadoop hadoop hadoop hadoop hadoop hadoop hadoop hadoop hadoop hadoop hadoop ...
- Confluence 6 配置服务器基础地址
服务器基础地址(Server Base URL)是用户访问 Confluence 的 URL 地址.这个基础的 URL 地址必须与你在浏览器中访问 Confluence 中的地址. Confluenc ...
- (七)STL适配器
1.适配器是稍微修改某些功能,比如三个参数改为两个参数,函数的名称改一下等等,可以出现在容器.迭代器和仿函数中. 2.适配器相当于对某个东西进行封装,例如A是B的适配器,则真正的功能实现是在B中,可以 ...