天天看點

模拟 javaScript Array 原型上的方法

Array.prototype.push

let arr = [,,,,]
let arrLike = {:,:,length:}
let obj = {}
/**
 * Array.prototype.push(element1,...,elementN)
 * 向數組末尾添加N個元素并且傳回數組長度
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/push
 * push 方法有意具有通用性。該方法和 call() 或 apply() 一起使用時,
 * 可應用在類似數組的對象上。push 方法根據 length 屬性來決定從哪裡開始插入給定的值。
 * 如果 length 不能被轉成一個數值,則插入的元素索引為 0,
 * 包括 length 不存在時。當 length 不存在時,将會建立它。
 */
Array.prototype.myPush = function() {
  var length = this.length ? this.length : (this.length = ) && 
  var index = 
  while (index < arguments.length) {
    this[length] = arguments[index]
    ++index
    ++length
  }
  this.length = length
  return this.length
}
arr.myPush(,,,)
Array.prototype.myPush.call(obj,,,{}) 
Array.prototype.myPush.call(arrLike,,,{})
console.log(arr)
console.log(obj)
console.log(arrLike)
複制代碼
           

Array.prototype.pop

/**
 * Array.prototype.pop()
 * 向數組末尾删除元素并且傳回該元素
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/pop
 * 從數組中删除的元素(當數組為空時傳回undefined)
 * pop 方法有意具有通用性。該方法和 call() 或 apply() 一起使用時,可應用在類似數組的對象上。
 * pop方法根據 length屬性來确定最後一個元素的位置。
 * 如果不包含length屬性或length屬性不能被轉成一個數值,會将length置為0,并傳回undefined。
 */
Array.prototype.myPop = function () {
  var length = this.length ? this.length : (this.length = ) && 
  if(length === )return
  var last = this[length]
  delete this[length - ]
  --this.length
  return last
}
console.log(Array.prototype.myPop.call(arr))
console.log(Array.prototype.myPop.call(arrLike))
console.log(arr,obj,arrLike)
複制代碼
           

Array.prototype.shift

/** 
 * Array.prototype.shift()
 * 向數組索引為0的位置删除元素并且傳回該元素
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/shift
 * shift 方法移除索引為 0 的元素(即第一個元素),并傳回被移除的元素,
 * 其他元素的索引值随之減 1。如果 length 屬性的值為 0 (長度為 0),則傳回 undefined。
 * shift 方法并不局限于數組:這個方法能夠通過 call 或 apply 方法作用于類似數組的對象上。
 * 但是對于沒有 length 屬性(從0開始的一系列連續的數字屬性的最後一個)的對象,調用該方法可能沒有任何意義。
 * 
*/ 
Array.prototype.myShift = function(){
  var length = this.length ? this.length : 
  if(length === )return
  var first = this[]
  var index = 
  while (index < this.length) {
    this[index - ] = this[index]
    index ++
  }
  delete this[length - ]
  --this.length
  return first
}
console.log(arr.myShift())
console.log(Array.prototype.myShift.call(obj))
console.log(Array.prototype.myShift.call(arrLike))
複制代碼
           

Array.prototype.unshift

/** 
 * Array.prototype.unshift(element1,...,elementN)
 * 向數組索引為0的位置插入N個元素并且傳回該數組長度
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift
 * unshift 方法會在調用它的類數組對象的開始位置插入給定的參數。
 * unshift 特意被設計成具有通用性;這個方法能夠通過 call 或 apply 方法作用于類數組對象上。
 * 不過對于沒有 length 屬性(代表從0開始的一系列連續的數字屬性的最後一個)的對象,調用該方法可能沒有任何意義。
 * 
*/ 
Array.prototype.myUnshift = function() {
  if(!this.length)return
  var length = this.length
  var arglength = arguments.length
  this.length = length + arglength
  var index = length - 
  while (index >= ) {
    this[index + arglength] = this[index]
    --index
  }
  index = arglength - 
  while (index >= ) {
    this[index] = arguments[index]
    --index
  }
  return this.length
}
console.log(arr.myUnshift(,,,,))
console.log(Array.prototype.myUnshift.call(obj,,,,,))
console.log(Array.prototype.myUnshift.call(arrLike,,,,,))
複制代碼
           

Array.prototype.slice

/** 
 * Array.prototype.slice(begin,end)
 * 方法傳回一個新的數組對象,這一對象是一個由 begin和 end(不包括end)決定的原數組的淺拷貝。原始數組不會被改變。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
 * slice 不修改原數組,隻會傳回一個淺複制了原數組中的元素的一個新數組。原數組的元素會按照下述規則拷貝:
 * 如果該元素是個對象引用 (不是實際的對象),slice 會拷貝這個對象引用到新的數組裡。
 * 兩個對象引用都引用了同一個對象。如果被引用的對象發生改變,則新的和原來的數組中的這個元素也會發生改變。
 * 對于字元串、數字及布爾值來說(不是 String、Number 或者 Boolean 對象),slice 會拷貝這些值到新的數組裡。
 * 在别的數組裡修改這些字元串或數字或是布爾值,将不會影響另一個數組。
 * 
*/ 
Array.prototype.mySlice = function(begin,end) {
  if(!this.length)return
  var arr = []
  var index = 
  begin = typeof begin === 'number' ? 
        begin <  ? this.length + begin 
        : begin 
        : 
  end =  typeof end === 'number' ? 
        end > this.length ? this.length 
        : end 
        : this.length
  while (begin < end) {
    arr[index] = this[begin]
    begin++
    index++
  }
  return arr
}
console.log(arr.mySlice())
console.log(Array.prototype.mySlice.call(obj,,))
console.log(Array.prototype.mySlice.call(arrLike,,))
複制代碼
           

Array.prototype.concat

/** 
 * Array.prototype.concat(item1,...,itemN)
 * 方法傳回一個新的數組對象,這一對象是一個由 begin和 end(不包括end)決定的原數組的淺拷貝。原始數組不會被改變。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
 * concat方法建立一個新的數組,它由被調用的對象中的元素組成,
 * 每個參數的順序依次是該參數的元素(如果參數是數組)或參數本身(如果參數不是數組)。它不會遞歸到嵌套數組參數中。
 * concat方法不會改變this或任何作為參數提供的數組,而是傳回一個淺拷貝
 * 
*/ 
Array.prototype.myConcat = function() {
  if(!arguments.length)return
  var arr = []
  var index = 
  while (index<this.length) {
    arr[index] = this[index]
    ++index
  }
  var i = 
  while (i < arguments.length) {
    var el = arguments[i]
    if(el instanceof Array) {
      if(el.length){
        var j = 
        while (j < el.length) {
          arr[index] = el[j]
          ++index
          ++j
        }
      }
    }else{
      arr[index] = el
      ++index
    }
    ++i
  }
  return arr
}
console.log(arr.myConcat(,[,],[,[,[],[]]]))
console.log(arr.concat(,[,],[,[,[],[]]]))
console.log(arr)
複制代碼
           

Array.prototype.splice

/** 
 * Array.prototype.splice(start,deleteCount,item1,...,itemN)
 * 方法通過删除或替換現有元素來修改數組,并以數組形式傳回被修改的内容。此方法會改變原數組。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
 * 如果添加進數組的元素個數不等于被删除的元素個數,數組的長度會發生相應的改變。
 * 
*/ 
Array.prototype.mySplice = function(start,deleteCount) {
  if(!this.length)return
  var arr = []
  /**
   * 如果超出了數組的長度,則從數組末尾開始添加内容;
   * 如果是負值,則表示從數組末位開始的第幾位(從-1計數);
   * 如果負數的絕對值大于數組的長度,則表示開始位置為第0位。
   */
  start = typeof start === 'number' ?
          start > this.length ? this.length 
        : start <  ? this.length + start <  ?  
        : this.length + start 
        : start 
        : 
  /** 
   * 如果 deleteCount 大于 start 之後的元素的總數,則從 start 後面的元素都将被删除(含第 start 位)。
   * 如果 deleteCount 被省略,則其相當于 array.length - start。
   * 如果 deleteCount 被省略了,或者它的值大于等于array.length - start(也就是說,如果它大于或者等于start之後的所有元素的數量),那麼start之後數組的所有元素都會被删除。
   * 如果 deleteCount 是 0 或者負數,則不移除元素。這種情況下,至少應添加一個新元素。
  */
  deleteCount = typeof deleteCount === 'number' ? 
              deleteCount <  ?  
            : deleteCount > this.length - start ? this.length - start 
            : deleteCount : deleteCount === undefined ? this.length - start 
            : 
  //取出除去前兩個參數之後的剩餘參數
  var args = arguments.length >  ? Array.prototype.mySlice.call(arguments,) : []
  var argLength = args.length

  //記錄一下開始位置
  var oIndex = start
  //需要新增或者縮減的數目
  var moveLength = argLength - deleteCount
  //需要删除到指定的下标
  var delIndex = deleteCount + start
  //新增到指定的下表
  var addIndex = argLength + start
  var index = 
  //删除 [...start, ... ,delIndex,...]
  while (start < delIndex) {
    arr[index] = this[start]
    this[start] = null
    ++start
    ++index
  }
  if(moveLength > ){
    //數組不足以插入的時候,開辟新的位置
    var i = this.length - 
    this.length += moveLength
    while (i >= oIndex) {
      this[i+moveLength] = this[i]
      --i
    }
  }else{
    //插入後還有剩餘,需要回縮空間
    var i = this.length
    if(start < this.length){
      while (start < i) {
        this[start+moveLength] = this[start]
        ++start
      }
    }
    this.length += moveLength
  }
  var i = 
  // 插入新的 item1...itemN
  while (oIndex < addIndex) {
    this[oIndex] = args[i]
    ++i
    ++oIndex
  }
  return arr
}
console.log(arrLike)
console.log(Array.prototype.mySplice.call(arrLike,,))
console.log(arrLike)
console.log(arr.mySplice())
console.log(arr)
複制代碼
           

Array.prototype.reduce

/**
 * Array.prototype.reduce(callback,initialValue)
 * reduce() 方法對數組中的每個元素執行一個由您提供的reducer函數(升序執行),将其結果彙總為單個傳回值。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
 * callback 執行數組中每個值的函數,包含四個參數:
  * accumulator: 累計器累計回調的傳回值; 它是上一次調用回調時傳回的累積值,或initialValue(見于下方)。
  * currentValue: 數組中正在處理的元素。
  * currentIndex可選: 數組中正在處理的目前元素的索引。 如果提供了initialValue,則起始索引号為0,否則為1。
  * array可選: 調用reduce()的數組
 * initialValue 可選
 * 作為第一次調用 callback函數時的第一個參數的值。 如果沒有提供初始值,則将使用數組中的第一個元素。 在沒有初始值的空數組上調用 reduce 将報錯。
 */
Array.prototype.myReduce = function(callback){
  var arr = this.mySlice()
  var len = arr.length
  var index = 
  var initialValue
  if(arguments.length >= ){
    //如果有預設值取預設值
    initialValue = arguments[] 
  }else{
    //如果沒有預設值,取第一個有值的索引,處理稀疏數組,若第一項沒有值的時候起始索引往後走
    while (index < len && !(arr[index] in arr)) {
      ++index
    }
    if(index >= len) return
    initialValue = arr[index++]
  }
  while (index < len) {
    if(arr[index] in arr){
      //值存在才走進來
      initialValue = callback.call(null, initialValue, arr[index], index, arr)
    }
    ++index
  }
  return initialValue
}
var sum = [,,,,].myReduce(function(accumulator, currentValue, currentIndex, array){
  console.log(accumulator, currentValue, currentIndex, array)
  return accumulator + currentValue;
}); // 10
var sum = [, , ,,,].myReduce(function(accumulator, currentValue, currentIndex, array){
  console.log(accumulator, currentValue, currentIndex, array)
  return accumulator + currentValue;
}); // 4
複制代碼
           

Array.prototype.reduceRight

/**
 * Array.prototype.reduceRight(callback,initialValue)
 * reduceRight() 方法對數組中的每個元素執行一個由您提供的reducer函數(降序執行),将其結果彙總為單個傳回值。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/reduceRight
 * callback 執行數組中每個值的函數,包含四個參數:
  * accumulator: 累計器累計回調的傳回值; 它是上一次調用回調時傳回的累積值,或initialValue(見于下方)。
  * currentValue: 數組中正在處理的元素。
  * currentIndex可選: 數組中正在處理的目前元素的索引。 如果提供了initialValue,則起始索引号為0,否則為1。
  * array可選: 調用reduceRight()的數組
 * initialValue 可選
 * 作為第一次調用 callback函數時的第一個參數的值。 如果沒有提供初始值,則将使用數組中的第一個元素。 在沒有初始值的空數組上調用 reduceRight 将報錯。
 */
Array.prototype.myReduceRight = function(callback){
  var arr = this.mySlice()
  var len = arr.length
  var index = len
  var initialValue
  if(arguments.length >= ){
    //如果有預設值取預設值
    initialValue = arguments[] 
  }else{
    //如果沒有預設值,取第一個有值的索引,處理稀疏數組,若最後一項項沒有值的時候起始索引往前走
    while (index >=  && !(arr[index] in arr)) {
      --index
    }
    if(index <= ) return
    initialValue = arr[index--]
  }
  while (index >= ) {
    if(arr[index] in arr){
      //值存在才走進來
      initialValue = callback.call(null, initialValue, arr[index], index, arr)
    }
    index--
  }
  return initialValue
}
var sum = [,,,,].myReduceRight(function(accumulator, currentValue, currentIndex, array){
  console.log(accumulator, currentValue, currentIndex, array)
  return accumulator + currentValue;
},); // 12
var sum = [, , ,,,].myReduceRight(function(accumulator, currentValue, currentIndex, array){
  console.log(accumulator, currentValue, currentIndex, array)
  return accumulator + currentValue;
},); // 6
複制代碼
           

Array.prototype.forEach

/**
 * Array.prototype.forEach(callback,context)
 * forEach() 方法對數組的每個元素執行一次提供的函數。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
 * callback 生成新數組元素的函數,使用三個參數:
    * currentValue
      * callback 數組中正在處理的目前元素。
    * index可選
      * callback 數組中正在處理的目前元素的索引。
    * array可選
      * callback  map 方法被調用的數組。
  * thisArg可選
    * 執行 callback 函數時使用的this 值。
 */
Array.prototype.myForEach = function(callback){
  var len = this.length
  var index = 
  var context = arguments[] || this
  while (index < len) {
    callback.call(context, this[index], index, this)
    index++
  }
}
[,,,,].forEach(function(current, index, arr) {
  console.log(current, index, arr, this.a)
},{a:})
[,,,,].myForEach(function(current, index, arr){
  console.log(current, index, arr, this.a)
},{a:})
複制代碼
           

Array.prototype.map

/**
 * Array.prototype.map(callback,context)
 * map() 方法建立一個新數組,其結果是該數組中的每個元素都調用一個提供的函數後傳回的結果。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/map
 * callback 生成新數組元素的函數,使用三個參數:
    * currentValue
      * callback 數組中正在處理的目前元素。
    * index可選
      * callback 數組中正在處理的目前元素的索引。
    * array可選
      * callback  map 方法被調用的數組。
  * thisArg可選
    * 執行 callback 函數時使用的this 值。
 */
Array.prototype.myMap = function(callback){
  var arr = []
  var len = this.length
  var index = 
  var context = arguments[] || this
  while (index < len) {
    arr.myPush(callback.call(context, this[index], index, this))
    index++
  }
  return arr
}
console.log([,,,,].map(function(current, index, arr) {
  console.log(current, index, arr)
  return index + this.a
},{a:})) //[1,2,3,4,5]
console.log([,,,,].myMap(function(current, index, arr) {
  console.log(current, index, arr)
  return index + this.a
},{a:})) //[1,2,3,4,5]
複制代碼
           

Array.prototype.filter

/**
 * Array.prototype.filter(callback,context)
 * filter() 方法建立一個新數組, 其包含通過所提供函數實作的測試的所有元素。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
 * callback 生成新數組元素的函數,使用三個參數:
    * currentValue
      * callback 數組中正在處理的目前元素。
    * index可選
      * callback 數組中正在處理的目前元素的索引。
    * array可選
      * callback  filter 方法被調用的數組。
  * thisArg可選
    * 執行 callback 函數時使用的this 值。
 */
Array.prototype.myFilter = function(callback){
  var arr = []
  var len = this.length
  var index = 
  var context = arguments[] || this
  while (index < len) {
    var el = this[index]
    callback.call(context, el, index, this) && arr.myPush(el)
    index++
  }
  return arr
}
console.log([,,,,].filter(function(current, index, arr) {
  console.log(current, index, arr)
  return index > this.a
},{a:}))
console.log([,,,,].myFilter(function(current, index, arr) {
  console.log(current, index, arr)
  return index > this.a
},{a:}))/**
 * Array.prototype.filter(callback,context)
 * filter() 方法建立一個新數組, 其包含通過所提供函數實作的測試的所有元素。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
 * callback 生成新數組元素的函數,使用三個參數:
    * currentValue
      * callback 數組中正在處理的目前元素。
    * index可選
      * callback 數組中正在處理的目前元素的索引。
    * array可選
      * callback  filter 方法被調用的數組。
  * thisArg可選
    * 執行 callback 函數時使用的this 值。
 */
Array.prototype.myFilter = function(callback){
  var arr = []
  var len = this.length
  var index = 
  var context = arguments[] || this
  while (index < len) {
    var el = this[index]
    callback.call(context, el, index, this) && arr.myPush(el)
    index++
  }
  return arr
}
console.log([,,,,].filter(function(current, index, arr) {
  console.log(current, index, arr)
  return index > this.a
},{a:}))//[3,4,5]
console.log([,,,,].myFilter(function(current, index, arr) {
  console.log(current, index, arr)
  return index > this.a
},{a:}))//[3,4,5]
複制代碼
           

Array.prototype.every

/**
 * Array.prototype.every(callback,context)
 * every() 方法測試數組的所有元素是否都通過了指定函數的測試。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/every
 * callback 生成新數組元素的函數,使用三個參數:
    * currentValue
      * callback 數組中正在處理的目前元素。
    * index可選
      * callback 數組中正在處理的目前元素的索引。
    * array可選
      * callback  every 方法被調用的數組。
  * thisArg可選
    * 執行 callback 函數時使用的this 值。
 */
Array.prototype.myEvery = function(callback){
  var every = true
  var len = this.length
  var index = 
  var context = arguments[] || this
  while (index < len) {
    if(!callback.call(context, this[index], index, this)) {
      every = false 
      break 
    }
    index++
  }
  return every
}
console.log([,,,,].every(function(current, index, arr) {
  console.log(current, index, arr)
  return current > this.a
},{a:})) // true
console.log([,,,,].myEvery(function(current, index, arr) {
  console.log(current, index, arr)
  return current > this.a
},{a:})) // true
複制代碼
           

Array.prototype.some

/**
 * Array.prototype.some(callback,context)
 * some() 方法測試是否至少有一個元素通過由提供的函數實作的測試。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/some
 * callback 生成新數組元素的函數,使用三個參數:
    * currentValue
      * callback 數組中正在處理的目前元素。
    * index可選
      * callback 數組中正在處理的目前元素的索引。
    * array可選
      * callback  some 方法被調用的數組。
  * thisArg可選
    * 執行 callback 函數時使用的this 值。
 */
Array.prototype.mySome = function(callback){
  var every = false
  var len = this.length
  var index = 
  var context = arguments[] || this
  while (index < len) {
    if(callback.call(context, this[index], index, this)) {
      every = true 
      break 
    }
    index++
  }
  return every
}
console.log([,,,,].some(function(current, index, arr) {
  console.log(current, index, arr)
  return current > this.a
},{a:})) // false
console.log([,,,,].mySome(function(current, index, arr) {
  console.log(current, index, arr)
  return current > this.a
},{a:})) // false
複制代碼
           

Array.prototype.find

/**
 * arr.find(callback[, thisArg]) 方法傳回數組中滿足提供的測試函數的第一個元素的值。否則傳回 undefined。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/find
 * callback
  * 在數組每一項上執行的函數,接收 3 個參數:
 * element
  * 目前周遊到的元素。
 * index可選
  * 目前周遊到的索引。
 * array可選
  * 數組本身。
 * thisArg可選
  * 執行回調時用作this 的對象。
*/
Array.prototype.myFind = function(callback,context) {
  context = context || window
  var len = this.length
  var i = 
  while (i < len) {
    if(callback.call(context,this[i],i,this))
      return this[i]
    i++
  }
  return undefined
}
console.log([, , , ].myFind(function(item) {
  return item + this.a > 
},{a:})); // 6
console.log([, , , ].find(function(item) {
  return item + this.a > 
},{a:})); // 6
複制代碼
           

Array.prototype.findIndex

/**
 * arr.findIndex(callback[, thisArg]) 方法傳回數組中滿足提供的測試函數的第一個元素的索引。否則傳回-1
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex
 * callback
  * 在數組每一項上執行的函數,接收 3 個參數:
 * element
  * 目前周遊到的元素。
 * index可選
  * 目前周遊到的索引。
 * array可選
  * 數組本身。
 * thisArg可選
  * 執行回調時用作this 的對象。
*/
Array.prototype.myFindIndex = function(callback,context) {
  context = context || window
  var len = this.length
  var i = 
  while (i < len) {
    if(callback.call(context,this[i],i,this))
      return i
    i++
  }
  return 
}
console.log([, , , ].myFindIndex(function(item) {
  return item + this.a > 
},{a:})); // 1
console.log([, , , ].findIndex(function(item) {
  return item + this.a > 
},{a:})); // 1
複制代碼
           

Array.prototype.join

/**
 * Array.prototype.join(separator)
 * join() 方法将一個數組(或一個類數組對象)的所有元素連接配接成一個字元串并傳回這個字元串。如果數組隻有一個項目,那麼将傳回該項目而不使用分隔符。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/join
 * separator 
 * 指定一個字元串來分隔數組的每個元素。如果需要,将分隔符轉換為字元串。
 * 如果省略(),數組元素用逗号分隔。預設為 ","。如果separator是空字元串(""),則所有元素之間都沒有任何字元。
 */
Array.prototype.myJoin = function(separator){
  var separator = typeof separator === 'string' ? separator : ','
  var len = this.length
  var str = ''
  if(!len) return str
  var index = 
  str = this[]  ? this[].toString() : '' 
  while (index < len) {
    str += separator + (this[index] ? this[index].toString() : '')
    index++
  }
  return str
}
console.log([,null,,{},[],//].myJoin(',') === [,null,,{},[],//].join(',')) //true

複制代碼
           

Array.prototype.reverse

/**
 * Array.prototype.reverse()
 * reverse()  方法将數組中元素的位置颠倒,并傳回該數組。該方法會改變原數組。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse
 * 方法颠倒數組中元素的位置,并傳回該數組的引用。
 */
Array.prototype.myReverse = function(){
  if(!this.length) return this
  var len = this.length - 
  var index = 
  var mid = Math.floor(this.length / )
  while (index < mid) {
    var lastIndex = len-index
    var tem = this[index]
    var last = this[lastIndex]
    var indexEmpty = !(index in this)
    var lastIndexEmpty = !(lastIndex in this)

    if(lastIndexEmpty){
      delete this[index]
    }else{
      this[index] = last
    }
    if(indexEmpty){
      delete this[lastIndex]
    }else{
      this[len-index] = tem
    }
    index++
  }
  return this
}
var arr1 = [,,,,,,,]
var arr2 = [,,,,,,,]
arr1.myReverse()
console.log(arr1) //[5, empty, 4, empty, 3, empty, 2, 1]
arr2.reverse()
console.log(arr2) //[5, empty, 4, empty, 3, empty, 2, 1]
複制代碼
           

Array.prototype.sort

/**
 * sort() 方法用原地算法對數組的元素進行排序,并傳回數組。排序算法現在是穩定的。預設排序順序是根據字元串Unicode碼點。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
 * compareFunction 可選
 * 用來指定按某種順序進行排列的函數。如果省略,元素按照轉換為的字元串的各個字元的Unicode位點進行排序。
  * firstEl
  * 第一個用于比較的元素。
  * secondEl
  * 第二個用于比較的元素。
 */
/**
 * 快排
 * @param {*} arr 待排序數組
 * @param {*} low 起點
 * @param {*} high 終點
 * @param {*} cb 比較函數
 */
function quickSort(arr,low,high,cb) {
  if(low<high){
    var mid = partition(arr,low,high,cb)
    quickSort(arr,low,mid,cb)
    quickSort(arr,mid+,high,cb)
  }
  return arr
}
/**
 * 劃分函數 
 */
function partition(arr,low,high,cb) {
  var poivt = arr[low]
  while (low<high) {
    while (low<high && cb(arr[high],poivt) >=  ) {
      high--
    }
    arr[low] = arr[high]
    while (low<high && cb(arr[low],poivt) <=  ) {
      low++
    }
    arr[high] = arr[low]
  }
  arr[low] = poivt
  return low
}
Array.prototype.mySort = function(cb) {
  return quickSort(this,,this.length,cb)
}


var arr1 = [,,,,,,,,,,,]
var arr2 = [,,,,,,,,,,,]
function fcb(a,b) {
  return a - b
}
console.log(arr1.mySort(fcb)) //[-1, 2, 3, 5, 5, 6, 8, 11, 41, 51, 52, 65]
console.log(arr2.sort(fcb)) //[-1, 2, 3, 5, 5, 6, 8, 11, 41, 51, 52, 65]
複制代碼
           

Array.prototype.indexOf

/**
 * indexOf() 方法傳回在數組中可以找到一個給定元素的第一個索引,如果不存在,則傳回-1。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
 * searchElement
  * 要查找的元素
 * fromIndex
  * 開始查找的位置。如果該索引值大于或等于數組長度,意味着不會在數組裡查找,傳回-1。
  * 如果參數中提供的索引值是一個負值,則将其作為數組末尾的一個抵消,
  * 即-1表示從最後一個元素開始查找,-2表示從倒數第二個元素開始查找 ,以此類推。
  * 注意:
  * 如果參數中提供的索引值是一個負值,并不改變其查找順序,
  * 查找順序仍然是從前向後查詢數組。如果抵消後的索引值仍小于0,則整個數組都将會被查詢。其預設值為0.
 */
Array.prototype.myIndexOf = function(search,fromIndex){
  fromIndex = fromIndex ? typeof fromIndex === 'number' ? fromIndex 
                : typeof fromIndex === 'string' ? (fromIndex-=) && fromIndex === fromIndex ? fromIndex 
                :  :  : 
  var index = 
  var len = this.length
  var i = fromIndex <  ? len + fromIndex : fromIndex
  while (i < len) {
    if(search == this[i]){
      index = i
      break
    }
    i++
  }
  return index
}
console.log(arr1.myIndexOf(,{}) == arr1.indexOf(,{})) //true
console.log(arr1.myIndexOf(,[]) == arr1.indexOf(,[])) //true
console.log(arr1.myIndexOf(,[]) == arr1.indexOf(,[])) //true
console.log(arr1.myIndexOf(,'1') == arr1.indexOf(,'1')) //true
console.log(arr1.myIndexOf(,'1e') == arr1.indexOf(,'1e')) //true
console.log(arr1.myIndexOf(,true) == arr1.indexOf(,true)) //true
console.log(arr1.myIndexOf(,NaN) == arr1.indexOf(,NaN)) //true
console.log(arr1.myIndexOf(,) == arr1.indexOf(,)) //true
console.log(arr1.myIndexOf(,) == arr1.indexOf(,)) //true
複制代碼
           

Array.prototype.lastIndexOf

/**
 * lastIndexOf() 方法傳回在數組中可以找到一個給定元素的第一個索引,如果不存在,則傳回-1。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf
 * searchElement
  * 要查找的元素
 * fromIndex
  * 從此位置開始逆向查找。預設為數組的長度減 1,即整個數組都被查找。
  * 如果該值大于或等于數組的長度,則整個數組會被查找。
  * 如果為負值,将其視為從數組末尾向前的偏移。
  * 即使該值為負,數組仍然會被從後向前查找。
  * 如果該值為負時,其絕對值大于數組長度,則方法傳回 -1,
  * 即數組不會被查找。
 */
Array.prototype.myLastIndexOf = function(search,fromIndex){
  fromIndex = fromIndex ? typeof fromIndex === 'number' ? fromIndex 
              : (fromIndex-=) && fromIndex === fromIndex ? fromIndex 
              :  
              : 
  var index = 
  var i = fromIndex <  ? fromIndex + this.length >  ? fromIndex + this.length :  : fromIndex > this.length ? this.length : fromIndex
  while (i > ) {
    if(search == this[i]){
      index = i
      break
    }
    i--
  }
  return index
}
console.log(arr1.myLastIndexOf(,{}) == arr1.lastIndexOf(,{})) //true
console.log(arr1.myLastIndexOf(,[]) == arr1.lastIndexOf(,[])) //true
console.log(arr1.myLastIndexOf(,[]) == arr1.lastIndexOf(,[])) //true
console.log(arr1.myLastIndexOf(,'1') == arr1.lastIndexOf(,'1')) //true
console.log(arr1.myLastIndexOf(,'1e') == arr1.lastIndexOf(,'1e')) //true
console.log(arr1.myLastIndexOf(,true) == arr1.lastIndexOf(,true)) //true
console.log(arr1.myLastIndexOf(,NaN) == arr1.lastIndexOf(,NaN)) //true
console.log(arr1.myLastIndexOf(,) == arr1.lastIndexOf(,)) //true
console.log(arr1.myLastIndexOf(,) == arr1.lastIndexOf(,)) //true
複制代碼
           

Array.prototype.from

/**
 * Array.from(arrayLike[, mapFn[, thisArg]]) 從一個類似數組或可疊代對象中建立一個新的數組執行個體。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/from
 * arrayLike
  * 想要轉換成數組的僞數組對象或可疊代對象。
 * mapFn (可選參數)
  * 如果指定了該參數,新數組中的每個元素會執行該回調函數。
 * thisArg (可選參數)
  * 可選參數,執行回調函數 mapFn 時 this 對象。  
*/
Array.prototype.myFrom = function(arrayLike,mapFn,context) {
  context = context || window
  mapFn = mapFn || function(item){return item}
  var arr = []
  if(arrayLike.forEach){
    arrayLike.forEach((value)=>{
      arr.push(mapFn.call(context,value))
    })
  }else{
    var length = arrayLike.length
    var i = 
    while (i<length) {
      arr.push(mapFn.call(context,arrayLike[i]))
      i++
    }
  }
  return arr
}
console.log(Array.prototype.myFrom(arrLike))
console.log(Array.prototype.myFrom(set))
console.log(Array.prototype.myFrom(map))
複制代碼
           

Array.prototype.of

/**
 * Array.of(element0[, element1[, ...[, elementN]]]) 方法建立一個具有可變數量參數的新數組執行個體,而不考慮參數的數量或類型。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/of
 * elementN
  * 任意個參數,将按順序成為傳回數組中的元素。  
*/
Array.prototype.myOf = function() {
  var len = arguments.length
  var arr =[]
  arr.length = len
  var i = 
  while (i < len) {
    arr[i] = arguments[i]
    i++
  }
  return arr
  // return Array.prototype.mySlice.call(arguments)
  // return Array.prototype.myFrom.call(null,arguments)
}
console.log(Array.prototype.myOf(,,))
console.log(Array.prototype.myOf(undefined))
console.log(Array.prototype.myOf())
複制代碼
           

Array.prototype.copyWithin

/**
 * Array.copyWithin(target[, start[, end]]) 方法淺複制數組的一部分到同一數組中的另一個位置,并傳回它,而不修改其大小。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin
 * target
  * 0 為基底的索引,複制序列到該位置。如果是負數,target 将從末尾開始計算。
  * 如果 target 大于等于 arr.length,将會不發生拷貝。如果 target 在 start 之後,複制的序列将被修改以符合 arr.length。
 * start
  * 0 為基底的索引,開始複制元素的起始位置。如果是負數,start 将從末尾開始計算。
  * 如果 start 被忽略,copyWithin 将會從0開始複制。
 * end
  * 0 為基底的索引,開始複制元素的結束位置。copyWithin 将會拷貝到該位置,但不包括 end 這個位置的元素。如果是負數, end 将從末尾開始計算。
  * 如果 end 被忽略,copyWithin 方法将會一直複制至數組結尾(預設為 arr.length)。  
*/
Array.prototype.myCopyWithin = function(target,start,end) {
  var len = this.length
  target = target <  ? Math.abs(target) > len ? len : len + target : target > len ? len : target
  start = typeof start === 'number' ? start <  ? Math.abs(start) > len ? len : len + start : start > len ? len : start : 
  end = typeof end === 'number' ? end <  ? Math.abs(end) > len ? len : len + end : end > len ? len : end : len
  var oTarget = target
  var offset = end - start
  var arr = Array.prototype.mySlice.call(this)
  while (target < len && (target-oTarget) < offset && start < end) {
    if(!this[start])break
    this[target] = arr[start]
    start++
    target++
  }
  return this
}
console.log([, , , , ].myCopyWithin()); // [1, 2, 3, 1, 2]
console.log([, , , , ].copyWithin()); // [1, 2, 3, 1, 2]
console.log([, , , , ].myCopyWithin(, )); // [4, 5, 3, 4, 5]
console.log([, , , , ].copyWithin(, )); // [4, 5, 3, 4, 5]
console.log([, , , , ].myCopyWithin(, , ));// [4, 2, 3, 4, 2]
console.log([, , , , ].copyWithin(, , ));// [4, 5, 3, 4, 5]
console.log([, , , , ].myCopyWithin(, , )); // [1, 2, 3, 3, 4]
console.log([, , , , ].copyWithin(, , )); // [1, 2, 3, 3, 4]
console.log([, , , , ].myCopyWithin(, , )); // [1, 2, 3, 3, 4]
console.log([, , , , ].copyWithin(, , )); // [1, 2, 3, 3, 4]
console.log([].myCopyWithin.call({length: , : }, , )); // {0: 1, 3: 1, length: 5}
console.log([].copyWithin.call({length: , : }, , )); // {0: 1, 3: 1, length: 5}
console.log([].myCopyWithin.call(new Int32Array([, , , , ]), , , ));// Int32Array [4, 2, 3, 4, 5]
console.log([].copyWithin.call(new Int32Array([, , , , ]), , , ));// Int32Array [4, 2, 3, 4, 5]
複制代碼
           

Array.prototype.fill

/**
 * Array.fill(callback[, thisArg]) 方法用一個固定值填充一個數組中從起始索引到終止索引内的全部元素。不包括終止索引。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/fill
 * value
  * 用來填充數組元素的值。
 * start 可選
  * 起始索引,預設值為0。
 * end 可選
  * 終止索引,預設值為 this.length。
*/
Array.prototype.myFill = function(value,start,end) {
  var len = this.length
  start = typeof start === 'number' ? start <  ? Math.abs(start) > len ? len : len + start : start > len ? len : start : 
  end = typeof end === 'number' ? end <  ? Math.abs(end) > len ? len : len + end : end > len ? len : end : len
  while (start < end) {
    this[start] = value
    start++
  }
  return this
}
console.log([, , ].myFill())               // [4, 4, 4]
console.log([, , ].myFill(, ))            // [1, 4, 4]
console.log([, , ].myFill(, , ))         // [1, 4, 3]
console.log([, , ].myFill(, , ))         // [1, 2, 3]
console.log([, , ].myFill(, , ))         // [1, 2, 3]
console.log([, , ].myFill(, , ))       // [4, 2, 3]
console.log([, , ].myFill(, NaN, NaN))     // [1, 2, 3]
console.log([, , ].myFill(, , ))         // [1, 2, 3]
console.log(Array().myFill())                // [4, 4, 4]
console.log(Array.prototype.myFill.call({ length:  }, ))  // {0: 4, 1: 4, 2: 4, length: 3}
複制代碼
           

Array.prototype.includes

/**
 * Array.prototype.includes(valueToFind[, fromIndex])方法用來判斷一個數組是否包含一個指定的值,根據情況,如果包含則傳回 true,否則傳回false。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
 * valueToFind
  * 需要查找的元素值。
 * fromIndex 可選
  * 從fromIndex 索引處開始查找 valueToFind。預設為 0。
  * 如果為負值,則按升序從 array.length + fromIndex 的索引開始搜 (即使從末尾開始往前跳 fromIndex 的絕對值個索引,然後往後搜尋)。
*/
Array.prototype.myIncludes = function(valueToFind,findIndex) {
  var len = this.length
  findIndex = typeof findIndex === 'number' ? findIndex <  ? Math.abs(findIndex) > len ? len : len + findIndex : findIndex > len ? len : findIndex : 
  while (findIndex < len) {
    var now = this[findIndex]
    if(valueToFind === now)return true
    if(valueToFind !== valueToFind && now !== now)return true
    findIndex++
  }
  return false
}
console.log([, , ].myIncludes())     // true
console.log([, , ].myIncludes())     // false
console.log([, , ].myIncludes(, ))  // false
console.log([, , ].myIncludes(, )) // true
console.log([, , NaN].myIncludes(NaN)) // true
複制代碼
           

Array.prototype.keys

/**
 * Array.prototype.keys()方法傳回一個包含數組中每個索引鍵的Array Iterator對象。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/keys
*/
Array.prototype.myKeys = function() {
  if(!typeof this === 'object')return 
  var arr = null
  var length = this.length
  if(!length){
    arr = []
    for (const key in this) {
      if (this.hasOwnProperty(key)) {
        arr.push(key)
      }
    }
  }
  var len = this.length || arr.length
  var nextIndex = 
  return {
    //[Symbol.iterator]需要在對象添加此屬性,才是一個可被 for...of 周遊的對象
    [Symbol.iterator]: function(){
      return {
        next:function(){
          return nextIndex < len ? {value: length ? nextIndex++ : arr[nextIndex++], done:false} : {done:true}
        }
      }
    }
  }
}
var a = ["a", "b", "c"].myKeys()
var b = Array.prototype.myKeys.call({:,:,length:})
var c = Array.prototype.myKeys.call({a:,b:})
for (const value of a) {
  console.log(value) // 0 1 2
}
for (const value of b) {
  console.log(value) // 0 1
}
for (const value of c) {
  console.log(value) // a b
}
複制代碼
           

Array.prototype.values

/**
 * Array.prototype.values()方法傳回一個新的 Array Iterator 對象,該對象包含數組每個索引的值。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/values
*/
Array.prototype.myValues = function() {
  if(!typeof this === 'object')return 
  var arr = this
  if(!this.length){
    arr = []
    for (const key in this) {
      if (this.hasOwnProperty(key)) {
        arr.push(this[key])
      }
    }
  }
  var len = this.length || arr.length
  var nextIndex = 
  return {
    //[Symbol.iterator]需要在對象添加此屬性,才是一個可被 for...of 周遊的對象
    [Symbol.iterator]: function(){
      return {
        next:function(){
          return nextIndex < len ? {value: arr[nextIndex++], done:false} : {done:true}
        }
      }
    }
  }
}
var a = ["a", 'b', "c"].myValues()
var b = Array.prototype.myValues.call({:,:,length:})
var c = Array.prototype.myValues.call({a:,b:})
for (const value of a) {
  console.log(value) // a b c
}
for (const value of b) {
  console.log(value) // 1 2
}
for (const value of c) {
  console.log(value) // 1 2
}
複制代碼
           

Array.prototype.entries

/**
 * Array.prototype.entries()方法傳回一個新的Array Iterator對象,該對象包含數組中每個索引的鍵/值對。
 * https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/entries
*/
Array.prototype.myEntries = function() {
  if(!typeof this === 'object')return 
  var arr = this
  var len = this.length || arr.length
  var nextIndex = 
  return {
    //[Symbol.iterator]需要在對象添加此屬性,才是一個可被 for...of 周遊的對象
    [Symbol.iterator]: function(){
      return {
        next:function(){
          return nextIndex < len ? {value:[nextIndex,arr[nextIndex++]], done:false} : {done:true}
        }
      }
    }
  }
}
var a = ["a", 'b', "c"].myEntries()
var b = Array.prototype.myEntries.call({:,:,length:})
for (const value of a) {
  console.log(value) // [0,"a"]  [0, "b"]  [0, "c"]
}
for (const value of b) {
  console.log(value) // [0, 1]  [0, 2]
}
複制代碼
           

轉載于:https://juejin.im/post/5ca973d95188254404522fcb

繼續閱讀