【简单版】手写数组 API

88 阅读1分钟

实现简单版的手写数组 API,后续更新完整版。

at

Array.prototype._at = function (index) {
  index = index < 0 ? index + this.length : index;

  if (index > this.length - 1 || index < 0) {
    return Error('index 取值错误');
  }

  return this[index];
};

concat

Array.prototype._concat = function (...valueN) {
  return [...this.slice(), ...valueN.flat()];
};

every

Array.prototype._every = function (callback, thisArg) {
  for (let i = 0; i < this.length; i++) {
    if (!callback.call(thisArg, this[i], i, this)) {
      return false;
    }
  }

  return true;
};

fill

Array.prototype._fill = function (value, start, end) {
  start = start || Number.isNaN(start) ? start : 0;
  end = end || Number.isNaN(start) ? end : this.length;

  if (isNaN(start)) {
    return this;
  }

  if (start > this.length) {
    return this;
  }

  if (start < 0) {
    start = start + this.length;
  }

  if (end < 0) {
    end = end + this.length;
  }

  if (end > this.length) {
    end = this.length;
  }

  for (let i = start; i < end; i++) {
    this[i] = value;
  }

  return this;
};

filter

Array.prototype._filter = function (callback, thisArg) {
  let result = [];

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

  return result;
};

find

Array.prototype._find = function (callback, thisArg) {
  for (let i = 0; i < this.length; i++) {
    if (callback.call(thisArg, this[i], i, this)) {
      return this[i];
    }
  }
};

findIndex

Array.prototype._findIndex = function (callback, thisArg) {
  for (let i = 0; i < this.length; i++) {
    if (callback.call(thisArg, this[i], i, this)) {
      return i;
    }
  }

  return -1;
};

flat

Array.prototype._flat = function (depth = 1) {
  function isArray(param) {
    return Object.prototype.toString.call(param).slice(8, -1) === 'Array';
  }

  const result = [];

  this.forEach(item => {
    if (isArray(item)) {
      if (depth > 0) {
        result.push(...item._flat(depth - 1));
      } else {
        result.push(item);
      }
    } else {
      result.push(item);
    }
  });

  return result;
};

forEach

Array.prototype._forEach = function (callback, thisArg) {
  const len = this.length;

  for (let i = 0; i < len; i++) {
    callback.call(thisArg, this[i], i, this);
  }
};

includes

Array.prototype._includes = function (valueToFind, fromIndex) {
  fromIndex = fromIndex ? (fromIndex < 0 ? fromIndex + this.length : fromIndex) : 0;

  for (let i = fromIndex; i < this.length; i++) {
    if (valueToFind === this[i] || (valueToFind !== valueToFind && this[i] !== this[i])) {
      return true;
    }
  }

  return false;
};

indexOf

Array.prototype._indexOf = function (searchElement, fromIndex) {
  fromIndex = fromIndex ? fromIndex : 0;

  if (fromIndex > this.length) {
    return -1;
  }

  if (fromIndex < 0) {
    fromIndex = this.length + fromIndex;
    if (fromIndex < 0) {
      fromIndex = 0;
    }
  }

  let index = fromIndex;

  while (index < this.length) {
    if (this[index] === searchElement) {
      return index;
    }
    index++;
  }

  return -1;
};

isArray

function isArray(param) {
  return Object.prototype.toString.call(param).slice(8, -1) === 'Array';
}

join

Array.prototype._join = function (separator) {
  separator = separator ? separator : ',';

  let result = '';

  for (let i = 0; i < this.length; i++) {
    result += `${this[i]}${separator}`;
  }

  return result.slice(0, -1);
};

lastIndexOf

Array.prototype._lastIndexOf = function (searchElement, fromIndex) {
  fromIndex = fromIndex ? fromIndex : this.length;

  if (fromIndex > this.length) {
    return -1;
  }

  if (fromIndex < 0) {
    fromIndex = this.length + fromIndex;
    if (fromIndex < 0) {
      fromIndex = 0;
    }
  }

  let index = fromIndex;

  while (index >= 0) {
    if (this[index] === searchElement) {
      return index;
    }
    index--;
  }

  return -1;
};

map

Array.prototype._map = function (callback, context) {
  let result = [];

  const context = context ? context : this;

  this.forEach((item, index) => {
    result.push(callback.call(context, item, index, me));
  });

  return result;
};

pop

Array.prototype._pop = function () {
  if (!this.length) {
    return undefined;
  }

  const delItem = this[this.length - 1];
  this.length = this.length - 1;

  return delItem;
};

push

Array.prototype._push = function (...elementList) {
  for (let i = 0; i < elementList.length; i++) {
    this[this.length + i] = elementList[i];
  }

  return this.length;
};

reduce

Array.prototype._reduce = function (callback, initialValue) {
  let i = initialValue ? 0 : 1;
  let result = initialValue ? initialValue : this[0];

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

  return result;
};

reverse

Array.prototype._reverse = function () {
  let left = 0;
  let right = this.length - 1;
  let temp;

  while (left < right) {
    temp = this[left];
    this[left] = this[right];
    this[right] = temp;
    left++;
    right--;
  }

  return this;
};

shift

Array.prototype._shift = function () {
  if (!this.length) {
    return undefined;
  }

  const returnItem = this[0];

  for (let i = 1; i < this.length; i++) {
    this[i - 1] = this[i];
  }

  this.length = this.length - 1;

  return returnItem;
};

slice

Array.prototype._slice = function (start, end) {
  const res = [];
  const { length } = this;

  if (start < 0) {
    start += length;
    if (start < 0) {
      start = 0;
    }
  } else {
    if (start > length) {
      start = length;
    }
  }

  if (end < 0) {
    end += length;
    if (end < 0) {
      end = 0;
    }
  } else {
    if (end > length) {
      end = length;
    }
  }

  for (let i = start; i < end; i++) {
    res.push(this[i]);
  }
  return res;
};

some

Array.prototype._some = function (fn, ctx) {
  for (let i = 0; i < this.length; i++) {
    if (fn.call(ctx, this[i], i, this)) {
      return true;
    }
  }

  return false;
};

splice

Array.prototype._splice = function (start, deleteCount, ...items) {
  let { length } = this;
  start = start || start === 0 ? start : 0;

  if (start < 0) {
    start = start + length;
    if (start < 0) {
      start = 0;
    }
  } else {
    if (start > length) {
      start = length;
    }
  }

  deleteCount = deleteCount || deleteCount === 0 ? deleteCount : length - start;
  if (deleteCount + start > length) {
    deleteCount = length;
  }
  if (deleteCount < 0) {
    deleteCount = 0;
  }

  const remainList = this.slice(start + deleteCount);
  const deletedItemList = this.slice(start, start + deleteCount);
  for (let i = 0; i < items.length; i++) {
    this[start + i] = items[i];
  }

  for (let i = 0; i < remainList.length; i++) {
    this[start + items.length + i] = remainList[i];
  }

  this.length = length - deleteCount + items.length;

  return deletedItemList;
};

toString

Array.prototype._toString = function () {
  let res = '';

  for (let i = 0; i < this.length - 1; i++) {
    res += `${this[i] },`;
  }

  res += this[this.length - 1];

  return res;
};

unshift

Array.prototype._unshift = function (...unshiftItemList) {
  for (let i = this.length - 1 + unshiftItemList.length; i > this.length - 1 - unshiftItemList.length; i--) {
    this[i] = this[i - unshiftItemList.length];
  }

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

  return this.length;
};