模擬 javaScript Array 原型上的方法

Array.prototype.push

let arr = [1,2,3,4,5]
let arrLike = {0:1,1:2,length:2}
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 = 0) && 0
  var index = 0
  while (index < arguments.length) {
    this[length] = arguments[index]
    ++index
    ++length
  }
  this.length = length
  return this.length
}
arr.myPush(1,2,3,4)
Array.prototype.myPush.call(obj,1,2,{}) 
Array.prototype.myPush.call(arrLike,3,4,{})
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 = 0) && 0
  if(length === 0)return
  var last = this[length-1]
  delete this[length - 1]
  --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 : 0
  if(length === 0)return
  var first = this[0]
  var index = 1
  while (index < this.length) {
    this[index - 1] = this[index]
    index ++
  }
  delete this[length - 1]
  --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 - 1
  while (index >= 0) {
    this[index + arglength] = this[index]
    --index
  }
  index = arglength - 1
  while (index >= 0) {
    this[index] = arguments[index]
    --index
  }
  return this.length
}
console.log(arr.myUnshift(0,1,3,4,5))
console.log(Array.prototype.myUnshift.call(obj,0,1,3,4,5))
console.log(Array.prototype.myUnshift.call(arrLike,0,1,3,4,5))
複製代碼

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 = 0
  begin = typeof begin === 'number' ? 
        begin < 0 ? this.length + begin 
        : begin 
        : 0
  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(-4))
console.log(Array.prototype.mySlice.call(obj,0,2))
console.log(Array.prototype.mySlice.call(arrLike,0,1))
複製代碼

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 = 0
  while (index<this.length) {
    arr[index] = this[index]
    ++index
  }
  var i = 0
  while (i < arguments.length) {
    var el = arguments[i]
    if(el instanceof Array) {
      if(el.length){
        var j = 0
        while (j < el.length) {
          arr[index] = el[j]
          ++index
          ++j
        }
      }
    }else{
      arr[index] = el
      ++index
    }
    ++i
  }
  return arr
}
console.log(arr.myConcat(1,[2,3],[4,[5,[6],[7]]]))
console.log(arr.concat(1,[2,3],[4,[5,[6],[7]]]))
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 < 0 ? this.length + start < 0 ? 0 
        : this.length + start 
        : start 
        : 0
  /** * 若是 deleteCount 大於 start 以後的元素的總數,則從 start 後面的元素都將被刪除(含第 start 位)。 * 若是 deleteCount 被省略,則其至關於 array.length - start。 * 若是 deleteCount 被省略了,或者它的值大於等於array.length - start(也就是說,若是它大於或者等於start以後的全部元素的數量),那麼start以後數組的全部元素都會被刪除。 * 若是 deleteCount 是 0 或者負數,則不移除元素。這種狀況下,至少應添加一個新元素。 */
  deleteCount = typeof deleteCount === 'number' ? 
              deleteCount < 0 ? 0 
            : deleteCount > this.length - start ? this.length - start 
            : deleteCount : deleteCount === undefined ? this.length - start 
            : 0
  //取出除去前兩個參數以後的剩餘參數
  var args = arguments.length > 2 ? Array.prototype.mySlice.call(arguments,2) : []
  var argLength = args.length

  //記錄一下開始位置
  var oIndex = start
  //須要新增或者縮減的數目
  var moveLength = argLength - deleteCount
  //須要刪除到指定的下標
  var delIndex = deleteCount + start
  //新增到指定的下表
  var addIndex = argLength + start
  var index = 0
  //刪除 [...start, ... ,delIndex,...]
  while (start < delIndex) {
    arr[index] = this[start]
    this[start] = null
    ++start
    ++index
  }
  if(moveLength > 0){
    //數組不足以插入的時候,開闢新的位置
    var i = this.length - 1
    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 = 0
  // 插入新的 item1...itemN
  while (oIndex < addIndex) {
    this[oIndex] = args[i]
    ++i
    ++oIndex
  }
  return arr
}
console.log(arrLike)
console.log(Array.prototype.mySplice.call(arrLike,1,1))
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 = 0
  var initialValue
  if(arguments.length >= 2){
    //若是有默認值取默認值
    initialValue = arguments[1] 
  }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 = [0,1,2,3,4].myReduce(function(accumulator, currentValue, currentIndex, array){
  console.log(accumulator, currentValue, currentIndex, array)
  return accumulator + currentValue;
}); // 10
var sum = [, 1, ,3,,].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-1
  var index = len
  var initialValue
  if(arguments.length >= 2){
    //若是有默認值取默認值
    initialValue = arguments[1] 
  }else{
    //若是沒有默認值,取第一個有值的索引,處理稀疏數組,若最後一項項沒有值的時候起始索引往前走
    while (index >= 0 && !(arr[index] in arr)) {
      --index
    }
    if(index <= 0) return
    initialValue = arr[index--]
  }
  while (index >= 0) {
    if(arr[index] in arr){
      //值存在才走進來
      initialValue = callback.call(null, initialValue, arr[index], index, arr)
    }
    index--
  }
  return initialValue
}
var sum = [0,1,2,3,4].myReduceRight(function(accumulator, currentValue, currentIndex, array){
  console.log(accumulator, currentValue, currentIndex, array)
  return accumulator + currentValue;
},2); // 12
var sum = [, 1, ,3,,].myReduceRight(function(accumulator, currentValue, currentIndex, array){
  console.log(accumulator, currentValue, currentIndex, array)
  return accumulator + currentValue;
},2); // 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 = 0
  var context = arguments[1] || this
  while (index < len) {
    callback.call(context, this[index], index, this)
    index++
  }
}
[1,2,3,4,5].forEach(function(current, index, arr) {
  console.log(current, index, arr, this.a)
},{a:1})
[1,2,3,4,5].myForEach(function(current, index, arr){
  console.log(current, index, arr, this.a)
},{a:1})
複製代碼

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 = 0
  var context = arguments[1] || this
  while (index < len) {
    arr.myPush(callback.call(context, this[index], index, this))
    index++
  }
  return arr
}
console.log([1,2,3,4,5].map(function(current, index, arr) {
  console.log(current, index, arr)
  return index + this.a
},{a:1})) //[1,2,3,4,5]
console.log([1,2,3,4,5].myMap(function(current, index, arr) {
  console.log(current, index, arr)
  return index + this.a
},{a:1})) //[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 = 0
  var context = arguments[1] || this
  while (index < len) {
    var el = this[index]
    callback.call(context, el, index, this) && arr.myPush(el)
    index++
  }
  return arr
}
console.log([1,2,3,4,5].filter(function(current, index, arr) {
  console.log(current, index, arr)
  return index > this.a
},{a:1}))
console.log([1,2,3,4,5].myFilter(function(current, index, arr) {
  console.log(current, index, arr)
  return index > this.a
},{a:1}))/** * 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 = 0
  var context = arguments[1] || this
  while (index < len) {
    var el = this[index]
    callback.call(context, el, index, this) && arr.myPush(el)
    index++
  }
  return arr
}
console.log([1,2,3,4,5].filter(function(current, index, arr) {
  console.log(current, index, arr)
  return index > this.a
},{a:1}))//[3,4,5]
console.log([1,2,3,4,5].myFilter(function(current, index, arr) {
  console.log(current, index, arr)
  return index > this.a
},{a:1}))//[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 = 0
  var context = arguments[1] || this
  while (index < len) {
    if(!callback.call(context, this[index], index, this)) {
      every = false 
      break 
    }
    index++
  }
  return every
}
console.log([1,2,3,4,5].every(function(current, index, arr) {
  console.log(current, index, arr)
  return current > this.a
},{a:0})) // true
console.log([1,2,3,4,5].myEvery(function(current, index, arr) {
  console.log(current, index, arr)
  return current > this.a
},{a:0})) // 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 = 0
  var context = arguments[1] || this
  while (index < len) {
    if(callback.call(context, this[index], index, this)) {
      every = true 
      break 
    }
    index++
  }
  return every
}
console.log([1,2,3,4,5].some(function(current, index, arr) {
  console.log(current, index, arr)
  return current > this.a
},{a:10})) // false
console.log([1,2,3,4,5].mySome(function(current, index, arr) {
  console.log(current, index, arr)
  return current > this.a
},{a:10})) // 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 = 0
  while (i < len) {
    if(callback.call(context,this[i],i,this))
      return this[i]
    i++
  }
  return undefined
}
console.log([4, 6, 8, 12].myFind(function(item) {
  return item + this.a > 10
},{a:5})); // 6
console.log([4, 6, 8, 12].find(function(item) {
  return item + this.a > 10
},{a:5})); // 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 = 0
  while (i < len) {
    if(callback.call(context,this[i],i,this))
      return i
    i++
  }
  return -1
}
console.log([4, 6, 8, 12].myFindIndex(function(item) {
  return item + this.a > 10
},{a:5})); // 1
console.log([4, 6, 8, 12].findIndex(function(item) {
  return item + this.a > 10
},{a:5})); // 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 = 1
  str = this[0]  ? this[0].toString() : '' 
  while (index < len) {
    str += separator + (this[index] ? this[index].toString() : '')
    index++
  }
  return str
}
console.log([1,null,,{},[],/2/].myJoin(',') === [1,null,,{},[],/2/].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 - 1
  var index = 0
  var mid = Math.floor(this.length / 2)
  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 = [1,2,,3,,4,,5]
var arr2 = [1,2,,3,,4,,5]
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-1,cb)
    quickSort(arr,mid+1,high,cb)
  }
  return arr
}
/** * 劃分函數 */
function partition(arr,low,high,cb) {
  var poivt = arr[low]
  while (low<high) {
    while (low<high && cb(arr[high],poivt) >= 0 ) {
      high--
    }
    arr[low] = arr[high]
    while (low<high && cb(arr[low],poivt) <= 0 ) {
      low++
    }
    arr[high] = arr[low]
  }
  arr[low] = poivt
  return low
}
Array.prototype.mySort = function(cb) {
  return quickSort(this,0,this.length-1,cb)
}


var arr1 = [3,5,5,-1,65,6,41,2,51,11,52,8]
var arr2 = [3,5,5,-1,65,6,41,2,51,11,52,8]
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-=0) && fromIndex === fromIndex ? fromIndex 
                : 0 : 0 : 0
  var index = -1
  var len = this.length
  var i = fromIndex < 0 ? len + fromIndex : fromIndex
  while (i < len) {
    if(search == this[i]){
      index = i
      break
    }
    i++
  }
  return index
}
console.log(arr1.myIndexOf(5,{}) == arr1.indexOf(5,{})) //true
console.log(arr1.myIndexOf(5,[]) == arr1.indexOf(5,[])) //true
console.log(arr1.myIndexOf(5,[1]) == arr1.indexOf(5,[1])) //true
console.log(arr1.myIndexOf(5,'1') == arr1.indexOf(5,'1')) //true
console.log(arr1.myIndexOf(5,'1e') == arr1.indexOf(5,'1e')) //true
console.log(arr1.myIndexOf(5,true) == arr1.indexOf(5,true)) //true
console.log(arr1.myIndexOf(5,NaN) == arr1.indexOf(5,NaN)) //true
console.log(arr1.myIndexOf(5,-1) == arr1.indexOf(5,-1)) //true
console.log(arr1.myIndexOf(5,-5) == arr1.indexOf(5,-5)) //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-=0) && fromIndex === fromIndex ? fromIndex 
              : 0 
              : 0
  var index = -1
  var i = fromIndex < 0 ? fromIndex + this.length > 0 ? fromIndex + this.length : 0 : fromIndex > this.length ? this.length : fromIndex
  while (i > 0) {
    if(search == this[i]){
      index = i
      break
    }
    i--
  }
  return index
}
console.log(arr1.myLastIndexOf(5,{}) == arr1.lastIndexOf(5,{})) //true
console.log(arr1.myLastIndexOf(5,[]) == arr1.lastIndexOf(5,[])) //true
console.log(arr1.myLastIndexOf(5,[1]) == arr1.lastIndexOf(5,[1])) //true
console.log(arr1.myLastIndexOf(5,'1') == arr1.lastIndexOf(5,'1')) //true
console.log(arr1.myLastIndexOf(5,'1e') == arr1.lastIndexOf(5,'1e')) //true
console.log(arr1.myLastIndexOf(5,true) == arr1.lastIndexOf(5,true)) //true
console.log(arr1.myLastIndexOf(5,NaN) == arr1.lastIndexOf(5,NaN)) //true
console.log(arr1.myLastIndexOf(5,-1) == arr1.lastIndexOf(5,-1)) //true
console.log(arr1.myLastIndexOf(5,-5) == arr1.lastIndexOf(5,-5)) //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 = 0
    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 = 0
  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(1,2,3))
console.log(Array.prototype.myOf(undefined))
console.log(Array.prototype.myOf(1))
複製代碼

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 < 0 ? Math.abs(target) > len ? len : len + target : target > len ? len : target
  start = typeof start === 'number' ? start < 0 ? Math.abs(start) > len ? len : len + start : start > len ? len : start : 0
  end = typeof end === 'number' ? end < 0 ? 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([1, 2, 3, 4, 5].myCopyWithin(-2)); // [1, 2, 3, 1, 2]
console.log([1, 2, 3, 4, 5].copyWithin(-2)); // [1, 2, 3, 1, 2]
console.log([1, 2, 3, 4, 5].myCopyWithin(0, 3)); // [4, 5, 3, 4, 5]
console.log([1, 2, 3, 4, 5].copyWithin(0, 3)); // [4, 5, 3, 4, 5]
console.log([1, 2, 3, 4, 5].myCopyWithin(0, 3, 4));// [4, 2, 3, 4, 2]
console.log([1, 2, 3, 4, 5].copyWithin(0, 3, 4));// [4, 5, 3, 4, 5]
console.log([1, 2, 3, 4, 5].myCopyWithin(-2, -3, -1)); // [1, 2, 3, 3, 4]
console.log([1, 2, 3, 4, 5].copyWithin(-2, -3, -1)); // [1, 2, 3, 3, 4]
console.log([1, 2, 3, 4, 5].myCopyWithin(3, 2, 4)); // [1, 2, 3, 3, 4]
console.log([1, 2, 3, 4, 5].copyWithin(3, 2, 4)); // [1, 2, 3, 3, 4]
console.log([].myCopyWithin.call({length: 5, 3: 1}, 0, 3)); // {0: 1, 3: 1, length: 5}
console.log([].copyWithin.call({length: 5, 3: 1}, 0, 3)); // {0: 1, 3: 1, length: 5}
console.log([].myCopyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4));// Int32Array [4, 2, 3, 4, 5]
console.log([].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4));// 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 < 0 ? Math.abs(start) > len ? len : len + start : start > len ? len : start : 0
  end = typeof end === 'number' ? end < 0 ? Math.abs(end) > len ? len : len + end : end > len ? len : end : len
  while (start < end) {
    this[start] = value
    start++
  }
  return this
}
console.log([1, 2, 3].myFill(4))               // [4, 4, 4]
console.log([1, 2, 3].myFill(4, 1))            // [1, 4, 4]
console.log([1, 2, 3].myFill(4, 1, 2))         // [1, 4, 3]
console.log([1, 2, 3].myFill(4, 1, 1))         // [1, 2, 3]
console.log([1, 2, 3].myFill(4, 3, 3))         // [1, 2, 3]
console.log([1, 2, 3].myFill(4, -3, -2))       // [4, 2, 3]
console.log([1, 2, 3].myFill(4, NaN, NaN))     // [1, 2, 3]
console.log([1, 2, 3].myFill(4, 3, 5))         // [1, 2, 3]
console.log(Array(3).myFill(4))                // [4, 4, 4]
console.log(Array.prototype.myFill.call({ length: 3 }, 4))  // {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 < 0 ? Math.abs(findIndex) > len ? len : len + findIndex : findIndex > len ? len : findIndex : 0
  while (findIndex < len) {
    var now = this[findIndex]
    if(valueToFind === now)return true
    if(valueToFind !== valueToFind && now !== now)return true
    findIndex++
  }
  return false
}
console.log([1, 2, 3].myIncludes(2))     // true
console.log([1, 2, 3].myIncludes(4))     // false
console.log([1, 2, 3].myIncludes(3, 3))  // false
console.log([1, 2, 3].myIncludes(3, -1)) // true
console.log([1, 2, 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 = 0
  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({0:1,1:2,length:2})
var c = Array.prototype.myKeys.call({a:1,b:2})
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 = 0
  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({0:1,1:2,length:2})
var c = Array.prototype.myValues.call({a:1,b:2})
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 = 0
  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({0:1,1:2,length:2})
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]
}
複製代碼
相關文章
相關標籤/搜索