js 数组从头添加到数组_编码练习:从头开始构建JavaScript数组方法

js 数组从头添加到数组

There's no better way to ensure that you understand how something works than building you're own version from scratch. In this article we are going to do just that by creating our own versions of Map, Reduce, Sort, and Filter from scratch. Here's the Codepen for reference.

没有比从头开始构建自己的版本更好的方法来确保您了解某些功能。 在本文中,我们将通过从头开始创建我们自己的Map,Reduce,Sort和Filter版本来做到这一点。 这是Codepen供参考。

By combining ES6 Arrow Functions with JavaScript Array functions, you can write extremely powerful and clean code!

通过将ES6箭头函数与JavaScript数组函数结合使用,您可以编写功能强大且简洁的代码!

TLDR (TLDR)

If you can write JavaScript array functions from scratch, you'll have a better understanding of how they work!

如果您可以从头开始编写JavaScript数组函数,则可以更好地了解它们的工作原理!

计划 ( The Plan )

Although it is not recommend, you can overwrite JavaScript functions pretty easily (we are only doing this for demo purposes!).

尽管不建议 这样做 ,但是您可以轻松覆盖JavaScript函数( 我们仅出于演示目的而这样做 !)。

JavaScript array functions are part of the Array prototype, just like functions on a class in Java, for example. We can overwrite prototype functions like so. Notice that I'm printing a message to the console to prove that the function has been overwritten when we call Array.prototype.map.

JavaScript数组函数是Array原型的一部分,就像Java中类的函数一样。 我们可以像这样覆盖原型函数。 注意,当我们调用Array.prototype.map时,我正在向控制台打印一条消息,以证明该函数已被覆盖。

const myCustomMapFunction = ( ) {
    console . log ( "My Custom Map Function!" ) ;
}
Array . prototype . map = myCustomMapFunction ;

JavaScript数组方法如何工作 ( How JavaScript Array Methods Work )

JavaScript Array methods heavily leverage ES6 Arrow Functions. If you're not familiar with ES6 Arrow Functions, I would recommend taking Wes Bos's free JavaScript 30 class.

JavaScript Array方法大量利用了ES6箭头功能。 如果您不熟悉ES6箭头函数,我建议您参加Wes Bos的免费JavaScript 30类。

Let's start with an example. Let's say you want to iterate through an array, increment each element (a number) by one, and return the new array. This is example what the Map function does. In the past, you would need to do several things to accomplish this.

让我们从一个例子开始。 假设您要遍历数组,将每个元素(一个数字)加1,然后返回新数组。 这是Map函数执行的示例。 过去,您需要做几件事来完成此任务。

  • initialize a new empty array

    初始化一个新的空数组
  • iterate through each element in th eoriginal array

    遍历原始数组中的每个元素
  • alter that element and put the altered value into the new array

    更改该元素并将更改后的值放入新数组

The code would look like this.

代码看起来像这样。

const arr = [ 1 , 2 , 3 ] ;
const newArray = [ ] ;

for ( let i = 0 ; i < arr . length ; i ++ ) {
   newArray [ i ] = arr [ i ] + 1 ;
}
return newArray ;

Not so bad, but with the built in Map Array function, you can accomplish this in one fancy line.

还算不错,但是借助内置的“地图数组”功能,您可以在一行中完成此操作。

return arr . map ( element => ++ element ) ;

Each of the Array functions we will cover accept a function as a parameter. They will iterate through each element of the array (just like we did above) and call that function to determine what to do with each element. After iterating through each element and calling the callback function, a new array or item (see reduce below) will be returned.

我们将介绍的每个Array函数都接受一个函数作为参数。 它们将遍历数组的每个元素(就像我们上面所做的一样),并调用该函数来确定如何处理每个元素。 遍历每个元素并调用回调函数后,将返回一个新的数组或项目(请参见下面的reduce)。

地图 ( Map )

Map iterates through each element, transforms it in some way, adds it to a new array, and returns the new array.

Map遍历每个元素,以某种方式对其进行转换,将其添加到新数组中,然后返回新数组。

Ok, let's actually build something and start with Map since we mentioned it above. Let's start by stubbing out the map function to prove that we can successfully override the original Map function.

好的,自从我们上面提到过以来,让我们实际构建一些东西并从Map开始。 让我们首先对map函数进行存根,以证明我们可以成功覆盖原始Map函数。

const myCustomMapFunction = ( callback ) {
    console . log ( "My Custom Map Function!" ) ;
}
Array . prototype . map = myCustomMapFunction ;

const arr = [ 1 , 2 , 3 ] ;

arr . map ( ) ;

If you run this code, you should see the appropriate log in the console. Good start! Now we can add the for loop and print out each element. Since the array itself is what calls the method, we get access to that array by referencing "this".

如果运行此代码,则应该在控制台中看到相应的日志。 好的开始! 现在我们可以添加for循环并打印出每个元素。 由于数组本身就是调用方法的对象,因此我们可以通过引用“ this”来访问该数组。

const myCustomMapFunction = ( callback ) {
    //this refers to the array
    for ( let i = 0 ; i < this . length ; i ++ ) {
        console . log ( this [ i ] ) ;
    }

}

Now, we need to perform whatever transformation is required by calling the callback function. When we do, we will pass a couple of things, the current element and the current index.

现在,我们需要通过调用回调函数执行所需的任何转换。 当我们这样做时,我们将传递一些东西,当前元素和当前索引。

const myCustomMapFunction = ( callback ) {
    //this refers to the array
    for ( let i = 0 ; i < this . length ; i ++ ) {
        const transformedElement = callback ( [ this [ i ] , i ) ;
    }

}

And lastly, add the transformed elements to a new array and return that array.

最后,将转换后的元素添加到新数组中并返回该数组。

const myCustomMapFunction = ( callback ) {
    const newArray = [ ] ;

    for ( let i = 0 ; i < this . length ; i ++ ) {
        newArray [ i ] = callback ( this [ i ] , i ) ;
    }

return newArray ;
}

过滤 ( Filter )

Filter returns a new array of elements filtered from the original array.

Filter返回从原始数组中过滤出来的元素的新数组。

Let's start by stubbing out our filter method.

让我们从暂存我们的过滤器方法开始。

const myCustomFilterFunction = ( ) {
    console . log ( "My Custom Filter Function!" ) ;
}
Array . prototype . filter = myCustomMapFunction ;

Now, let's set up the for loop to iterate through each element.

现在,让我们设置for循环以遍历每个元素。

const myCustomFilterFunction = ( callback ) {
    const newArray = [ ] ;

    for ( let i = 0 ; i < this . length ; i ++ ) {
        console . log ( this [ i ] ) ;
    }

}

Inside of the for loop, we need to decided whether or not to add each element to the new array. This is the purpose of the callback function, so we use it to conditionally add each element. If the return value is false, push the element on to the return array.

在for循环中,我们需要确定是否将每个元素添加到新数组中。 这是回调函数的目的,因此我们使用它有条件地添加每个元素。 如果返回值为false,则将元素压入返回数组。

const myCustomFilterFunction = ( callback ) {
    const newArray = [ ] ;

    for ( let i = 0 ; i < this . length ; i ++ ) {
        if ( callback ( this [ i ] ) {
            newArray . push ( this [ i ] ) ;
        }

    }

    return newArray ;

}

分类 ( Sort )

Sort returns a sorted array from the original array.

排序从原始数组返回排序后的数组。

Let's start again by stubbing out out sort function with a for loop.

让我们重新开始,使用for循环取消sort函数。

const myCustomSortFunction = ( callback ) {
    const newArray = [ ] ;

    for ( let i = 0 ; i < this . length ; i ++ ) {
        console . log ( this [ i ] ) ;
    }
}
Array . prototype . filter = myCustomMapFunction ;

Now things start to get a bit different. We are going to be using Bubble Sort. Here's the strategy.

现在事情开始变得有些不同了。 我们将使用Bubble Sort 。 这是策略。

  • repeatedly iterate through items in array

    重复遍历数组中的项目
  • compare adjacent itmes and swap if they are not in order

    比较相邻的item,如果顺序不对则交换
  • after iterating through n^2 times, the array is sorted

    迭代n ^ 2次后,对数组进行排序

Disclaimer *- *I'm not focusing on the most efficient way to sort, just the easiest for this demo.

免责声明* -* 并不是在关注最有效的排序方式 ,而只是本次演示中最简单的排序方式

With Bubble Sort, you have to iterate through the array fully once for each element in the array. This calls for a nested for loop where the inner loop iterates through stopping one short of the final element, so we can add that now.

使用冒泡排序,您必须对数组中的每个元素完全遍历数组一次。 这需要一个嵌套的for循环,其中,内部循环通过停止最后一个元素的结尾来进行迭代,因此我们现在可以添加它。

const myCustomSortFunction = ( callback ) {
    const newArray = [ ] ;

    for ( let i = 0 ; i < newArray . length ; i ++ ) {
        for ( let j = 0 ; j < newArray . length - 1 ; j ++ ) { 
        }
    }
}

We also don't want to alter the original array. To avoid this, we can create copy the original array into the new array using the Spread Operator.

我们也不想更改原始数组。 为了避免这种情况,我们可以使用Spread Operator将原始数组复制到新数组中。

const myCustomSortFunction = ( callback ) {
    const newArray = [ ... this ] ;

    for ( let i = 0 ; i < newArray . length ; i ++ ) {
        for ( let j = 0 ; j < newArray . length - 1 ; j ++ ) { 
        }
    }
}

The callback function takes two parameters, the current element and the next element, and will return whether or not they are in order. In our case, if the callback function returns a number greater than zero, we want to swap the two elements.

回调函数接受两个参数,当前元素和下一个元素,并将返回它们是否按顺序排列。 在我们的例子中,如果回调函数返回的数字大于零,则我们希望交换两个元素。

const myCustomSortFunction = ( callback ) {
    const newArray = [ ... this ] ;

    for ( let i = 0 ; i < newArray . length ; i ++ ) {
        for ( let j = 0 ; j < newArray . length - 1 ; j ++ ) {             
            if ( callback ( newArray [ j ] , newArray [ j + 1 ] ) > 0 ) {
                // swap the elements
            }
        }
    }
}

To swap the elements, we make a copy of one, replace the first one, then replace the second one with the copy. When we are finished, we return the newly sorted array.

要交换元素,我们制作一个副本,替换第一个,然后用副本替换第二个。 完成后,我们返回新排序的数组。

Array . prototype . sort = function ( callback ) {
  const newArray = [ ... this ] ; 

  for ( let i = 0 ; i < newArray . length ; i ++ ) {
    for ( let j = 0 ; j < newArray . length - 1 ; j ++ ) {         
        if ( callback ( newArray [ j ] , newArray [ j + 1 ] ) > 0 ) {
            const temp = retVal [ j + 1 ] ;
            retVal [ j + 1 ] = retVal [ j ] ;
            retVal [ j ] = temp ;
        }
    } 
  }
  //array is sorted
  return newArray ;
}

减少 ( Reduce )

Reduce iterates through each element and returns one single value

Reduce遍历每个元素并返回一个单一值

Reduce does not return a new array like these other functions. It actually "reduces" the elements in an array to one final value, a number, a string, an object, etc. The easiest example for using reduce is you want to sum up all the elements in a number array. Let's start with stubbing the function out like we did previously.

Reduce不会像其他函数那样返回新数组。 它实际上将数组中的元素“归约”为一个最终值,一个数字,一个字符串,一个对象等。使用reduce的最简单示例是要对一个数字数组中的所有元素求和。 让我们从像以前一样对函数进行存根开始。

const myCustomReduceFunction = ( callback ) {
    console . log ( "My Custom Reduce Function!" ) ;
}
Array . prototype . reduce = myCustomReduceFunction ;

const arr = [ 1 , 2 , 3 ] ;

arr . reduce ( ) ;

For Reduce to return one final value, it needs a starting value to work with. The callback function that the user passes along will determine how to update this "accumulator" based on each element of the array and return it at the end. The callback function must return the updated accumulator.

为了使Reduce返回一个最终值,它需要一个起始值才能使用。 用户传递的回调函数将根据数组的每个元素确定如何更新此“累加器”,并在最后将其返回。 回调函数必须返回更新的累加器

We can add our for loop now, and make a call to the callback function. The return value becomes the new accumulator. After the loop ends, we return the accumulator.

我们现在可以添加for循环,并调用回调函数。 返回值将成为新的累加器。 循环结束后,我们返回累加器。

const myCustomReduceFunction = ( callback , accumulator ) {

    for ( let i = 0 ; i < this . length ; i ++ ) {
        accumulator = callback ( accumulator , this [ i ] , index ) ;
    }
    return accumulator ;
}

回顾 ( Recap )

I'm a big believer in understanding how things work behind the scenes, and this level of understanding is important while learning a new language, framework, etc. If you take the time to dig in and really learn how things work, you'll be much better off!

我坚信要了解事物在幕后的运作方式 ,这种理解水平对于学习新的语言,框架等非常重要。如果您花时间深入研究并真正了解事物的运作方式,您将好多了!

翻译自: https://scotch.io/tutorials/coding-exercise-build-javascript-array-methods-from-scratch

js 数组从头添加到数组

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值