复制代码 代码如下,除了使用朴素的循环转换以

作者: 前端  发布:2019-10-04

高贵的数组降维——Javascript中apply方法的妙用

2016/02/18 · JavaScript · apply, 数组

原来的作品出处: ralph_zhu   

将多维数组(极度是二维数组)转化为一维数组是事情支付中的常用逻辑,除了运用节约财富的巡回转换以外,我们仍可以使用Javascript的言语特色实现更为精简高雅的调换。本文将从节约的大循环调换最早,逐个介绍三种常用的转变方法,并借此轻易回看Array.prototype.concat方法和Function.prototype.apply方法。
以下代码将以把二维数组降维到一维数组为例。

  1. 刻苦的转移

JavaScript

function reduceDimension(arr) { var reduced = []; for (var i = 0; i < arr.length; i++) { for (var j = 0; j < arr[i].length; j++) { reduced.push(arr[i][j]); } } return reduced; }

1
2
3
4
5
6
7
8
9
function reduceDimension(arr) {
    var reduced = [];
    for (var i = 0; i < arr.length; i++) {
        for (var j = 0; j < arr[i].length; j++) {
            reduced.push(arr[i][j]);
        }
    }
    return reduced;
}

此措施思路简单,利用再度循环遍历二维数组中的每一个成分并置于新数组中。

 

  1. 利用concat转换
    先来回想一下MDN上对于该措施的牵线:
    “concat creates a new array consisting of the elements in the object on which it is called, followed in order by, for each argument, the elements of that argument (if the argument is an array) or the argument itself (if the argument is not an array).”

即假若concat方法的参数是贰个因素,该因素会被直接插入到新数组中;假如参数是多少个数组,该数组的次第要素将被插入到新数组中;将该天性应用到代码中:

JavaScript

function reduceDimension(arr) { var reduced = []; for (var i = 0; i < arr.length; i++){ reduced = reduced.concat(arr[i]); } return reduced; }

1
2
3
4
5
6
7
function reduceDimension(arr) {
    var reduced = [];
    for (var i = 0; i < arr.length; i++){
        reduced = reduced.concat(arr[i]);
    }
    return reduced;
}

arr的每一个要素都以八个数组,作为concat方法的参数,数组中的每三个子元素又都会被单独插入进新数组。
采纳concat方法,大家将再一次循环简化为了单重循环。

 

  1. 利用apply和concat转换
    遵从惯例,先来回看一下MDN上对此apply方法的牵线:
    “The apply() method calls a function with a given this value and arguments provided as an array.”

即apply方法会调用三个函数,apply方法的率先个参数会作为被调用函数的this值,apply方法的第2个参数(贰个数组,或类数组的对象)会作为被调用对象的arguments值,也正是说该数组的依次要素将会相继成为被调用函数的次第参数;将该性情应用到代码中:

function reduceDimension(arr) { return Array.prototype.concat.apply([], arr); }

1
2
3
function reduceDimension(arr) {
    return Array.prototype.concat.apply([], arr);
}

arr作为apply方法的首个参数,本人是二个数组,数组中的每二个成分(依旧数组,即二维数组的第二维)会被充作参数依次传入到concat中,效果一样[].concat([1,2], [3,4], [5,6])。
运用apply方法,大家将单重循环优化为了一行代码,很轻便有型有木有啊~

读者也可参谋本文思路,自身行使递归完成N维数组降维的逻辑。

3 赞 8 收藏 评论

图片 1

在标准浏览器中,好像只要对象存在length属性,就可以把它调换为数组,但IE就不尽然。

1.indexOf和lastIndexOf方法:

javascript框架设计读书笔记之数组的庞大与修复,javascript读书笔记

1.indexOf和lastIndexOf方法:

因为IE7在数组对象上行使indexOf会报错,所以供给重写三个包容性的。

复制代码 代码如下:

Array.prototype.lastIndexOf(item,index){
  var n = this.length,i = (index==null||index>n-1)?n-1:index;
  if(i < 0) i = n+i;
  for(;i>=0;i--)
    if(this[i] === item)   //全等看清,indexOf,lastIndexOf
      return i;
  return -1;
}

2.shuffle艺术:对数组实行洗牌。

复制代码 代码如下:

function shuffle(target){
  var i = target.length, j ,temp;
  for(;i>0;j=parseInt(Math.random() * i), x = target[--i],target[i] = target[j],target[j]=x){}   
     //假设length=10,那么Math.random()*10->[0,10),parseInt后,[0,9],随机的挑三拣四一个与数组最终一项交流。第三回巡回,[0,8],与数组的尾数第二项沟通。
  return target;
}

3.数组的平坦化管理:flatten,重回二个一维数组

复制代码 代码如下:

function flatten(arr){
  var result = [];
  arr.forEach(function(item){
    if(Array.isArray(item))   result.concat(flatten(item));
    else  result.push(item);
  });
  return result;
}

4.unique办法:对数组去重操作

此格局,面试官最欣赏问了,因为它有三种达成情势,最常见的是四个for循环。日常精通的最多的是行使四个指标a,然后一个for循环数组arr,每一次if(a[arr[i]])是不是留存,不设有则push到你新定义的数组result中。存在就印证,重复,由此不要push到result中。这种方案,针对"123",123,会以为一样的,其实三个是字符串,叁个是数字,不应有认为是一样的。

由此就出现了以下格局:[1,"1","1"]

复制代码 代码如下:

 if ((typeof obj[array[i]]) != (typeof array[i]) || obj[array[i]] != array[i]) {
  a.push(array[i]);
  obj[array[i]] = array[i];
}

//首先推断项目是还是不是相同,假若同样,就判别他们的值是还是不是等于,不对等就存进去,相等就印证以前早就存在那些值了。

只要类型分化样,这里存在三种景况,

率先种情景,obj以前已经存了此数量了,比方:obj[123] = 123,现在array[i] = "123",这时,typeof obj[array[i]])是数字,而typeof array[i]是字符串,由此存入数组中。

其次种情景是obj还没存此数据,举例:array[i] = "123",obj["123"] = undefind,这时typeof obj[array[i]])就是typeof undefined = undefined,不等于typeof array[i],存入数组中。

此种方法,能够缓慢解决字符串和数字一样的事态,不过不可能消除对象一样的情形。比方:a = {1:2}, b ={2:1};

第贰次巡回时,typeof obj[a] = undefined,typeof a = Object。存入obj[a] =a.其实正是obj[Object] = a;

首次巡回时,typeof obj[b] 等于typeof obj[Object]实际上便是typeof a = object,typeof b = object.因而进来到obj[array[i]] != array[i]|,也就是obj[b]->obj[Object]->a != b,由此存入

obj[b] = b;也就是obj[Object] = b;覆盖了事先的obj[Object] = a;

这种情景下,就能够现出全数的目的,都只会存最终七个目的值。

当牵记对象时,俺就能够采纳以下这种情势:

复制代码 代码如下:

for(var i = 0; i < temp.length; i++){
                for(var j = i + 1; j < temp.length; j++){
                        if(temp[i] === temp[j]){
                                temp.splice( j, 1 );
                                j--;
                        }
                }
        }
 return temp;

5.数组排序:sort方法,假若要排序的是指标,能够本身写贰个compare(a,b){if(a.age>b.age) return 1;else return -1;},A.sort(compare).

6.min回到数组最小值:return Math.min.apply(0,array);

7.unshift在ie6,7下不回来数主管度。

复制代码 代码如下:

if([].unshift(1)!==1)   //往空数组中从前边增加一项,其余浏览器会回来1,而IE6,7不会回来数主管度。那时就实行if语句
{
  var _unshift = Array.prototype.unshift;      //函数威迫。
  Array.prototype.unshift = function(){
    _unshift.apply(this,arguments);
    return this.length;
  }
}

8.splice在一个参数的景色下,IE8以及以下版本暗中认可第2个参数为0,而其他浏览器是数高管度。

复制代码 代码如下:

if([1,2,3].splice(1).length == 0)   //IE8以及以下版本会等于0,别的版本会等于3,步入if里面
{
  var _splice = Array.prototype.splice;
  Array.prototype.splice = function(a){
    if(arguments.length == 1)   //借使只有三个参数时
    {
      return _splice.call(this,a,this.length);
    }else{
      return _splice.apply(this,arguments);
    }
  }
}

其一方法会改动数组的选项,因而数组的push,pop,shift,unshift(那多少个法子也会修改数组的选用)都会调用那一个主意来贯彻。

此处有一个地方须要专一:

复制代码 代码如下:

var color = new Array('red','blue','yellow','black');
var color2 = color.splice(2,0,'brown','pink');
alert(color); // red,blue,brown,pink,yellow,black,在yellow选项上,开头操作,如若剔除为0,则拉长的选择是在yellow从前插入。切记。

 
这里请大家去看下splice和slice的分别,再次回到值,以及对原数组的影响。

以上就是本节的内容的精简版了,纵然轻易,但最重要都在,希望对我们阅读本节的时候能享有利于

1.indexOf和lastIndexOf方法: 因为IE7在数组对象上选取indexOf会报错,所以需求...

[Ctrl+A 全选 注:如需引进外界Js需刷新技巧实行]

因为IE7在数组对象上利用indexOf会报错,所以须要重写叁个宽容性的。

继之大家看看各大类库的拍卖:

复制代码 代码如下:

复制代码 代码如下:

Array.prototype.lastIndexOf(item,index){
  var n = this.length,i = (index==null||index>n-1)?n-1:index;
  if(i < 0) i = n+i;
  for(;i>=0;i--)
    if(this[i] === item)   //全等推断,indexOf,lastIndexOf
      return i;
  return -1;
}

//jQuery的makeArray
var makeArray = function( array ) {
var ret = [];
if( array != null ){
var i = array.length;
// The window, strings (and functions) also have 'length'
if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
ret[0] = array;
else
while( i )
ret[--i] = array[i];
}
return ret;
}

2.shuffle方法:对数组进行洗牌。

jQuery对象是用来存款和储蓄与管理dom成分的,它重要依赖于setArray方法来安装与保养长度与索引,而setArray的参数要求是贰个数组,由此makeArray的身价非常重大。那办法保障固然未有参数也要赶回二个空数组。
Prototype.js的$A方法

复制代码 代码如下:

复制代码 代码如下:

function shuffle(target){
  var i = target.length, j ,temp;
  for(;i>0;j=parseInt(Math.random() * i), x = target[--i],target[i] = target[j],target[j]=x){}   
     //假设length=10,那么Math.random()*10->[0,10),parseInt后,[0,9],随机的选料叁个与数组最终一项交流。第二遍巡回,[0,8],与数组的尾数第二项调换。
  return target;
}

function $A(iterable) {
if (!iterable) return [];
if (iterable.toArray) return iterable.toArray();
var length = iterable.length || 0, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
}

3.数组的平坦化管理:flatten,再次来到三个一维数组

mootools的$A方法

复制代码 代码如下:

复制代码 代码如下:

function flatten(arr){
  var result = [];
  arr.forEach(function(item){
    if(Array.isArray(item))   result.concat(flatten(item));
    else  result.push(item);
  });
  return result;
}

function $A(iterable){
if (iterable.item){
var l = iterable.length, array = new Array(l);
while (l--) array[l] = iterable[l];
return array;
}
return Array.prototype.slice.call(iterable);
};

4.unique格局:对数组去重操作

Ext的toArray方法

此形式,面试官最爱怜问了,因为它有三种实现格局,最常见的是八个for循环。平常精通的最多的是应用贰个对象a,然后八个for循环数组arr,每便if(a[arr[i]])是不是存在,不真实则push到你新定义的数组result中。存在就印证,重复,由此不用push到result中。这种方案,针对"123",123,会认为一样的,其实三个是字符串,二个是数字,不该感觉是一律的。

复制代码 代码如下:

所以就出现了以下措施:[1,"1","1"]

var toArray = function(){
return isIE ?
function(a, i, j, res){
res = [];
Ext.each(a, function(v) {
res.push(v);
});
return res.slice(i || 0, j || res.length);
} :
function(a, i, j){
return Array.prototype.slice.call(a, i || 0, j || a.length);
}
}()

复制代码 代码如下:

Ext的准备比较玄妙,功效也相比强硬。它一齐初就自动施行本人,今后就绝不剖断浏览器了。它还恐怕有多少个可选参数,对转移的纯数组进行操作。
最后看dojo的_toArray,dojo的落实一连那么奇怪的。 和Ext同样,前面多少个参数是可选,只然则第三个是偏移量,最终二个是已有些数组,用于把新生的新组成分合併过去。

 if ((typeof obj[array[i]]) != (typeof array[i]) || obj[array[i]] != array[i]) {
  a.push(array[i]);
  obj[array[i]] = array[i];
}

复制代码 代码如下:

//首先推断项目是还是不是同样,假诺同样,就决断他们的值是还是不是等于,不对等就存进去,相等就证实以前早就存在那么些值了。

(function(){
var efficient = function(obj, offset, startWith){
return (startWith||[]).concat(Array.prototype.slice.call(obj, offset||0));
};
var slow = function(obj, offset, startWith){
var arr = startWith||[];
for(var x = offset || 0; x >obj.length; x++){
arr.push(obj[x]);
}
return arr;
};
dojo._toArray =
dojo.isIE ? function(obj){
return ((obj.item) ? slow : efficient).apply(this, arguments);
} :
efficient;
})();

只要类型不均等,这里存在三种情况,

您恐怕感兴趣的小说:

  • JavaScript中的类数组对象介绍
  • JavaScript 里的类数组对象
  • js 用于检查实验类数组对象的函数方法
  • JQuery $.each遍历JavaScript数组对象实例
  • js使用Array.prototype.sort()对数组对象排序的方法
  • js接收并转化Java中的数组对象的办法
  • JS从非数组对象转数组的秘籍小结
  • javascript Array数组对象的扩大函数代码
  • JavaScript类数组对象转换为数组对象的不二法门实例深入分析

率先种景况,obj此前已经存了此数量了,例如:obj[123] = 123,现在array[i] = "123",这时,typeof obj[array[i]])是数字,而typeof array[i]是字符串,由此存入数组中。

其次种情况是obj还没存此数据,比如:array[i] = "123",obj["123"] = undefind,这时typeof obj[array[i]])就是typeof undefined = undefined,不等于typeof array[i],存入数组中。

此种方法,能够缓和字符串和数字同样的情景,不过不可能化解对象同样的场合。举例:a = {1:2}, b ={2:1};

第3回巡回时,typeof obj[a] = undefined,typeof a = Object。存入obj[a] =a.其实正是obj[Object] = a;

第三回巡回时,typeof obj[b] 等于typeof obj[Object]其实便是typeof a = object,typeof b = object.由此进来到obj[array[i]] != array[i]|,也就是obj[b]->obj[Object]->a != b,由此存入

obj[b] = b;也就是obj[Object] = b;覆盖了事先的obj[Object] = a;

这种景况下,就能够油但是生全数的目的,都只会存最后二个对象值。

当考虑对象时,小编就能够接纳以下这种措施:

复制代码 代码如下:

for(var i = 0; i < temp.length; i++){
                for(var j = i + 1; j < temp.length; j++){
                        if(temp[i] === temp[j]){
                                temp.splice( j, 1 );
                                j--;
                        }
                }
        }
 return temp;

5.数组排序:sort方法,假诺要排序的是目的,能够本人写三个compare(a,b){if(a.age>b.age) return 1;else return -1;},A.sort(compare).

6.min回去数组最小值:return Math.min.apply(0,array);

7.unshift在ie6,7下不回去数首席营业官度。

复制代码 代码如下:

if([].unshift(1)!==1)   //往空数组中以前边加多一项,其他浏览器会回来1,而IE6,7不会回去数老总度。那时就实施if语句
{
  var _unshift = Array.prototype.unshift;      //函数威吓。
  Array.prototype.unshift = function(){
    _unshift.apply(this,arguments);
    return this.length;
  }
}

8.splice在一个参数的景况下,IE8以及以下版本暗中同意第四个参数为0,而其他浏览器是数COO度。

复制代码 代码如下:

if([1,2,3].splice(1).length == 0)   //IE8以及以下版本会等于0,别的版本会等于3,步入if里面
{
  var _splice = Array.prototype.splice;
  Array.prototype.splice = function(a){
    if(arguments.length == 1)   //倘使唯有二个参数时
    {
      return _splice.call(this,a,this.length);
    }else{
      return _splice.apply(this,arguments);
    }
  }
}

其一方法会更改数组的选项,因而数组的push,pop,shift,unshift(那多少个章程也会修改数组的挑三拣四)都会调用这么些方法来完结。

此间有一个地点供给静心:

复制代码 代码如下:

var color = new Array('red','blue','yellow','black');
var color2 = color.splice(2,0,'brown','pink');
alert(color); // red,blue,brown,pink,yellow,black,在yellow选项上,初步操作,倘若去除为0,则增加的选料是在yellow在此以前插入。切记。

 
此处请我们去看下splice和slice的界别,重回值,以及对原数组的熏陶。

如上就是本节的剧情的精简版了,固然轻易,但重点都在,希望对大家阅读本节的时候能具有协理

您只怕感兴趣的小说:

  • 十温火热的JavaScript框架和库
  • 深切剖判JavaScript框架Backbone.js中的事件机制
  • JavaScript框架是怎么?怎么最先艺叫做框架?
  • 相当赞的动手创制JavaScript框架的详实教程
  • javascript框架设计等等工厂
  • javascript框架设计之浏览器的嗅探和本性侦测
  • javascript框架布置之种子模块
  • javascript框架统一妄想之框架分类及重大功用
  • 二〇一五年最销路广的21款JavaScript框架推荐
  • javascript框架设计读书笔记之字符串的扩大和修补
  • javascript框架陈设读书笔记之模块加载系统
  • javascript框架统一希图读书笔记之种子模块
  • JavaScript框架(iframe)操作计算
  • 怎么取舍Javascript框架(Javascript Framework)
  • 详见介绍8款超实用JavaScript框架
  • brook javascript框架介绍
  • 16个最盛行的JavaScript框架[推荐]
  • 什么抉择符合你的JavaScript框架

本文由9159.com发布于前端,转载请注明出处:复制代码 代码如下,除了使用朴素的循环转换以

关键词:

上一篇:没有了
下一篇:没有了