предисловие
Я пишу вопросы по программированию по интервью недавно. Я часто пользуюсь массивами и часто хочу быть ленивым. Я использую методы, предоставляемые им, но я все еще нефессию в использовании методов массива, что приводит к написанию много мусора. Простой, Эффективный и элегантный 👊
Итак, ✍Эта статья основана на понимании характеристик массивов JavaScript, как следует из названия.
"Другие статьи:"
❝❞
- 9 основных операций связанного списка "Алгоритмы и структуры данных"👍
- [Практично 👍] Порекомендуйте несколько отличных интерфейсных веб-сайтов.
- (Рекомендуется интенсивное чтение) Отправьте вам 54 вопроса для собеседования по JavaScript
- [Полная искренность👍] Советы по отладке Chrome DevTools, эффективность➡️🚀🚀🚀
- [Предложение👍] Продолжайте с 100 ответными вопросами JS, кислыми и крутыми (всего 1,8 Вт слов + консолидация основы JS)
- [1.2W word👍] Читы на девушку - как работает браузер (Часть 1)
- [1.1W word] Читы на девушку - как работает браузер (процесс рендеринга)
"Как реализовать общие методы массива самостоятельно через исходный код array.js в v8", если вы хотите улучшить свои навыки программирования, вы можете остаться и прочитать эту статью
"После прочтения вы получите 👏"
- Больше ясности в общих методах работы с массивами
- Как написать общие массивы вручную
Если вам это нравится, вы можете лайкнуть / подписаться и поддержать его.Я надеюсь, что вы можете прочитать эту статью и получить что-то.
❝Точка где нужно скачать код этой статьиGitHub
❞
Начнем эту статью 🉑
Основы массива
Если вы хотите написать методы массива вручную, вы должны сначала восполнить основы, и вы должны сначала иметь возможность использовать их API.
создать массив
//字面量
let demo = [1, 2, 3]
// 构造器
let demo1 = Array(),
demo2 = Array(3),
demo3 = Array(1,2,3),
demo4 = new Array(1,2,3);
метод в конструкторе
Array.of()
Простое понимание заключается в том, чтобы создать экземпляр нового массива, вы можете увидеть разницу с конструктором массива
грамматика:
Array.of(element0[, element1[, ...[, elementN]]])
Применение:
Array.of(7); // [7]
Array.of(1, 2, 3); // [1, 2, 3]
Array(7); // [ , , , , , , ]
Array(1, 2, 3); // [1, 2, 3]
Разница между ними:Array.of(7)создать один элемент7массив иArray(7)Создайте пустой массив длиной 7 (**Примечание:** Это относится к массиву с 7 пустыми местами, а не к массиву из 7undefinedмассив компонентов).
Array.isArray()
Array.isArray()Используется для определения того, является ли переданное значениеArray.
Array.isArray([1, 2, 3]);
// true
Array.isArray({foo: 123});
// false
Array.isArray("foobar");
// false
Array.isArray(undefined);
// false
Ручная реализация
// Array.isArray
if(!Array.isArray){
Array.isArray = obj => Object.prototype.toString.call(obj) === '[object Array]'
}
Чтобы судить о типе данных JS, вы можете посмотреть блог, который я написал ранее.Поговорим о принципе реализации typeof instanceof
Array.from()
Array.from()Метод создает новый экземпляр массива с неглубокой копией из массивоподобного или итерируемого объекта.
Array.from(arrayLike[, mapFn[, thisArg]])
параметр
- arrayLike: требуется, вы можете передать 1, подобный массиву (аргументg) 2, итерируемый объект (набор, карта).
- mapFn: необязательно, эквивалентно Array.from(arrayLike).map(mapFn, thisArg).
- thisArg: необязательный, этот объект при выполнении функции обратного вызова mapFn. Очень полезно для развязки. Обрабатываемые данные могут быть отделены от объекта, дескриптор функции обработки определяется в thisArg, который используется для возврата результата после вызова дескриптора в mapFn.
Применение
String
// Array.from()
const demo = Array.from('123')
console.log(demo) //[ 'a', 'b', 'c' ]
new Set()
const Array_demo = Array.from(new Set([1,2,3,4,1,2,3]))
console.log(Array_demo) // [1,2,3,4]
new Map()
const map = new Map([[1, 2], [2, 4], [4, 8]]);
Array.from(map);
// [[1, 2], [2, 4], [4, 8]]
массивный
const fn = (function() {
const demo = Array.from(arguments);
console.log(demo);
})(1,2,3); // [ 1, 2, 3 ]
Развязка массива
let fn = function () {
console.log(arguments)
const Arr_new = [].concat.apply([],arguments)
return Array.from(new Set(Arr_new))
}
const demo1 = [1, 2, 3, 4],
demo2 = [4,5,6,2,2,2],
demo3 = [1,2,3,4,2,2,3,4];
console.log(fn(demo1,demo2,demo3))
// [1,2,3,4,5,6]
В полной мере используйте третий параметр thisArg
const obj = {
handle: x => x * 4
}
console.log(Array.from([11, 22, 33], function (x) {
return this.handle(x)
}, obj))
// [44, 88, 132]
идеи
- Определить, является ли arrayLike пустым
- Судя по mapFn это конструктор, это конструктор, при каждом обходе пусть arr[i] = mapFn(iValue,i), когда не конструктор, arr[i] = iValue
- Определить, существует ли thisArg, если он существует arr[i] = mapFn.call(thisArg, iValue,i)
Справочный исходный код находится в V8Строка 1763 array.js начинает путешествие Array.from
/**
* 实现Array.from
* toInteger方法:返回一个整数
* toLength方法: 保证len数字合法[0~Number.MAX_SAFE_INTEGER]
* Number.MAX_SAFE_INTEGER = Math.pow(2,53) - 1
* 判断arrayLike 为 空 抛出错误
* mapFn非空并且不是构造函数抛出错误
* 每次遍历arrayLike,如果mapFn存在, arr[i] = mapFn(iValue,i) 不存在的话 arr[i] = iValue
* 判断thisArg是否存在,存在的话 arr[i] = mapFn.call(thisArg, iValue,i)
* */
Array.myfrom = (function () {
const toStr = Object.prototype.toString
const isCallable = fn => typeof fn === 'function' || toStr.call(fn) === '[object Function]'
const toInteger = value => {
const v = Number(value)
if(isNaN(v)) return 0
// 无穷大或者0 直接返回
if(v === 0 || !isFinite(v)) return v
return (v > 0 ? 1 : -1) * Math.floor(Math.abs(v))
}
// 最大的范围Number.MAX_SAFE_INTEGER
const maxSafeInteger = Number.MAX_SAFE_INTEGER
const toLength = value => {
const len = toInteger(value)
return Math.min(maxSafeInteger, Math.max(0, len))
}
return function myfrom (arrayLike/*, mapFn, thisArg*/) {
const that = this
if(arrayLike === null) throw new TypeError("Array.from requires an array-like object - not null or undefined")
const items = Object(arrayLike)
let thisArg = ''
// 判断mapFn是否undefined, 这里最好不要直接使用undefined,因为undefined不是保留字,
// 很有可能undefined是个值 最好用 void 0 或者 void undefined
const mapFn = arguments.length > 1 ? arguments[1] : void 0
if( typeof mapFn !== 'undefined') {
// 接下来判断第二个参数是不是构造函数
if( !isCallable(mapFn) ) throw new TypeError("Array.from when provided mapFn must be a function")
if( arguments.length > 2) thisArg = arguments[2]
}
const len = toLength(items.length)
const arr = isCallable(that) ? Object(new that(len)) : new Array(len)
let i = 0,
iValue;
while ( i < len) {
iValue = items[i]
if(mapFn) arr[i] = typeof thisArg === 'undefined' ? mapFn(iValue,i) : mapFn.call(thisArg, iValue, i)
else
arr[i] = iValue
i++
}
arr.length = len
return arr
}
})()
👍Должен сказать, что после реализации Array.from() я на самом деле много чего добился.
общий метод
Для облегчения запоминания и поиска основные методы разделены на три категории: Методы обхода массива, которые модифицируют исходный метод массива и возвращают новый метод массива.
метод обхода
Всего существует 12 способов обхода массива в js без изменения исходного массива:
ES5:
forEach、every 、some、 filter、map、reduce、reduceRight、
ES6:
find、findIndex、keys、values、entries
forEach()
грамматика:
array.forEach(callback(currentValue, index, arr), thisArg)
параметр:
callback:为数组中每个元素执行的函数,该函数接收一至三个参数
currentValue 数组中正在处理的当前元素
index (可选) 数组中正在处理的当前元素的索引
arr (可选) forEach() 方法正在操作的数组
thisArg 可选参数,当执行回调函数callback,用作this值
Давайте поговорим об использовании thisArg
function Counter() {
this.sum = 0;
this.count = 0;
}
Counter.prototype.add = function(array) {
array.forEach(function(entry) {
this.sum += entry;
++this.count;
}, this);
// ^---- Note
};
const obj = new Counter();
obj.add([2, 5, 9]);
obj.count;
// 3 === (1 + 1 + 1)
obj.sum;
// 16 === (2 + 5 + 9)
Очевидно, this, переданное в строке 9, определяет проблему, на которую указывает this в функции обратного вызова forEach.
В строке 14 obj вызывает метод add, поэтому this указывает на obj, то есть this в forEach указывает на объект obj.
**Примечание.** При использованииВыражение функции стрелкипередать параметры функции,
thisArgАргументы игнорируются, поскольку стрелочные функции связаны лексическиthisстоимость
Взгляните на array.js в исходном коде v8.Строка 1258 начинает путешествие forEach.
Давайте попробуем сымитировать и написать один:
/**
* Array.prototype.forEach(callback, thisArg)
* 除了抛出异常外,无法终止或者跳出forEach()循环
* 遍历数组
**/
Array.prototype.myforEach = function (callback, thisArg) {
if( this == null ) throw new TypeError("this is null or not defined")
let newArr = Object(this)
let len = newArr.length >>> 0
if( typeof callback !== 'function' ) throw new TypeError(callback + ' is not a function');
let thatArg = arguments.length >= 2 ? arguments[1] : void 0
let k = 0
while( k < len ) {
if(k in newArr){
callback.call(thatArg, newArr[k], k, newArr);
}
k++
}
return void 0
}
С точки зрения кода нужно обратить внимание:
- Невозможно выйти из цикла на полпути, каждый раз, когда вы вызываете функцию обратного вызова, return может выйти только из этого обратного вызова.
- Метод возвращает значение undefined, даже если вы возвращаете значение, оно бесполезно.
- Что thisArg изменяет, так это this в функции обратного вызова, как видно из исходного кода, и если функция обратного вызова является стрелочной функцией, мы знаем, что стрелочная функция не может изменить это, поэтому thisArg будет проигнорирован
every()
определение:
Проверяет, все ли элементы в массиве проходят тест указанной функции. Он возвращает логическое значение.
грамматика:
array.every(function(currentValue, index, arr), thisArg)
параметр:
callback:为数组中每个元素执行的函数,该函数接收一至三个参数
currentValue 数组中正在处理的当前元素
index (可选) 数组中正在处理的当前元素的索引
arr (可选) every() 方法正在操作的数组
thisArg 可选参数,当执行回调函数callback,用作this值
Применение:
function isBigEnough(element, index, array) {
return element >= 10;
}
[12, 5, 8, 130, 44].every(isBigEnough); // false
[12, 54, 18, 130, 44].every(isBigEnough); // true
Взгляните на array.js в исходном коде v8.С линии 1322 начинается каждое путешествие
/**
* Array.prototype.every(callback, thisArg)
**/
Array.prototype.myevery = function (callback, thisArg) {
if( this == null ) throw new TypeError("this is null or not defined")
let newArr = Object(this)
let len = newArr.length >>> 0
if( typeof callback !== 'function' ) throw new TypeError(callback + ' is not a function');
let thatArg = arguments.length >= 2 ? arguments[1] : void 0
let k = 0
while( k < len ) {
if(k in newArr){
let testResult = callback.call(thatArg, newArr[k], k, newArr);
if( !testResult ) return false
}
k++
}
return true
}
С точки зрения кода нужно обратить внимание:
- В случае пустого массива, пока первый параметр является функцией обратного вызова, все возвращает true
- Чтобы возвращать true каждый раз, возвращайте true в конце, иначе false
- Если параметр thisArg присутствует, то
callbackкогда звонятthisзначение, глобальный объект в нестрогом режиме, переданный в строгом режимеundefined, видетьthisВход. - каждый не изменяет исходный массив
-
everyИтерация по диапазону элементов в первом вызовеcallbackЭто было определено ранее. вызовeveryЭлементы, добавленные в массив позже, не будутcallbackдоступ к. Если элементы, присутствующие в массиве, изменены, они переходят вcallbackЗначениеeveryдоступ к их стоимости в данный момент. Доступ к удаленным элементам или элементам, которым никогда не присваивалось значение, невозможен.
some
определение:
Проверяет, проходит ли хотя бы один элемент в массиве предоставленный функциональный тест. Возвращает значение типа Boolean
грамматика:
array.some(function(currentValue, index, arr), thisArg)
параметр:
callback:为数组中每个元素执行的函数,该函数接收一至三个参数
currentValue 数组中正在处理的当前元素
index (可选) 数组中正在处理的当前元素的索引
arr (可选) some() 方法正在操作的数组
thisArg 可选参数,当执行回调函数callback,用作this值
Применение:
function isBiggerThan10(element, index, array) {
return element > 10;
}
[2, 5, 8, 1, 4].some(isBiggerThan10); // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true
//此例中为模仿 includes() 方法, 若元素在数组中存在, 则回调函数返回值为 true :
var fruits = ['apple', 'banana', 'mango', 'guava'];
function checkAvailability(arr, val) {
return arr.some(function(arrVal) {
return val === arrVal;
});
}
checkAvailability(fruits, 'kela'); // false
checkAvailability(fruits, 'banana'); // true
Взгляните на array.js в исходном коде v8.Строка 1298 начинает какое-то путешествие
/**
* 测试数组中是不是至少有1个元素通过了被提供的函数测试
* Array.prototype.some(callback, thisArg)
**/
Array.prototype.mysome = function (callback, thisArg) {
if (this == null) throw new TypeError("this is null or not defined")
let newArr = Object(this)
let len = newArr.length >>> 0
if (typeof callback !== 'function') throw new TypeError(callback + ' is not a function');
let thatArg = arguments.length >= 2 ? arguments[1] : void 0
for (let i = 0; i < len; i++) {
if (i in newArr && callback.call(thatArg, newArr[i], i, newArr))
return true
}
return false
}
С точки зрения кода нужно обратить внимание:
- некоторые не меняют исходный массив
- При тестировании с пустым массивом в любом случае возвращается
false - Если ваша callback-функция не имеет возвращаемого значения, она каждый раз не определена, а также возвращается результат вызова some в конце.
false - Передача thisArg, значение this в функции обратного вызова, зависит от правила указания this.
filter
определение:
Создает новый массив, содержащий все элементы теста, реализованного предоставленной функцией.
грамматика:
let newArray = array.filter(function(currentValue, index, arr), thisArg)
параметр:
callback:为数组中每个元素执行的函数,该函数接收一至三个参数
currentValue 数组中正在处理的当前元素
index (可选) 数组中正在处理的当前元素的索引
arr (可选) filter() 方法正在操作的数组
thisArg 可选参数,当执行回调函数callback,用作this值
Применение:
function isBigEnough(element) {
return element >= 10;
}
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// filtered is [12, 130, 44]
var fruits = ['apple', 'banana', 'grapes', 'mango', 'orange'];
/**
* Array filters items based on search criteria (query)
*/
function filterItems(query) {
return fruits.filter(function(el) {
return el.toLowerCase().indexOf(query.toLowerCase()) > -1;
})
}
console.log(filterItems('ap')); // ['apple', 'grapes']
console.log(filterItems('an')); // ['banana', 'mango', 'orange']
Взгляните на array.js в исходном коде v8.Строка 1245 начинает путь к фильтру
/**
* 创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
* Array.prototype.filter(callback, thisArg)
*
*/
Array.prototype.myfilter = function (callback, thisArg) {
if (this == null) throw new TypeError("this is null or not defined")
let newArr = Object(this)
let len = newArr.length >>> 0
if (typeof callback !== 'function') throw new TypeError(callback + ' is not a function');
let thatArg = arguments.length >= 2 ? arguments[1] : void 0,
resultArr = new Array(len),
count = 0
for (let i = 0; i < len; i++) {
if (i in newArr) {
if (typeof thatArg === 'undefined' && callback(newArr[i], i, newArr))
resultArr[count++] = newArr[i]
if (typeof thatArg !== 'undefined' && callback.call(thatArg, newArr[i], i, newArr))
resultArr[count++] = newArr[i]
}
}
resultArr.length = count
return resultArr
}
С точки зрения кода нужно обратить внимание:
- Пользовательская функция обратного вызова должна иметь логическое возвращаемое значение. Если она не записывает возвращаемое значение по умолчанию, равное undefined, тогда логическое значение должно быть ложным.
- Не изменяет исходный массив, а возвращает новый массив, содержащий все элементы теста, реализованного предоставленной функцией.
- Возвращает пустой массив, если не передано ни одного элемента
-
filterне изменяет исходный массив, он возвращает новый отфильтрованный массив -
filterИтерация по диапазону элементов в первом вызовеcallbackЭто было определено ранее. вызовfilterЭлементы, добавленные в массив позже, не будутfilterпройти к. Если существующие элементы были изменены, они переходят вcallbackЗначениеfilterПерейдите к их значению на данный момент. Элементы, которые удалены или которым никогда не присваивалось значение, не просматриваются. - если
filterобеспечитьthisArgпараметр, он будет использоваться какcallbackкогда звонятthisстоимость. иначе,callbackизthisЗначением будет глобальный объект в нестрогом режиме и в строгом режиме.undefined.callbackФункция, наконец, наблюдаетthisЗначения основаны на обычномПравила для «этого» с точки зрения функцииопределенный. - Обратите особое внимание на указатель this в функции стрелки.
map
определение:
Создает новый массив, результатом которого является то, что каждый элемент массива является возвращаемым значением одного вызова предоставленной функции обратного вызова.
грамматика:
let newArray = array.map(function(currentValue, index, arr), thisArg)
параметр:
callback:为数组中每个元素执行的函数,该函数接收一至三个参数
currentValue 数组中正在处理的当前元素
index (可选) 数组中正在处理的当前元素的索引
arr (可选) map() 方法正在操作的数组
thisArg 可选参数,当执行回调函数callback,用作this值
Применение:
//数组中每个元素的平方根
var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt);
// roots的值为[1, 2, 3], numbers的值仍为[1, 4, 9]
var numbers = [1, 4, 9];
var doubles = numbers.map(function(num) {
return num * 2;
});
// doubles数组的值为: [2, 8, 18]
// numbers数组未被修改: [1, 4, 9]
//演示如何在一个 String 上使用 map 方法获取字符串中每个字符所对应的 ASCII 码组成的数组:
var map = Array.prototype.map
var a = map.call("Hello World", function(x) {
return x.charCodeAt(0);
})
// a的值为[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
Взгляните на array.js в исходном коде v8.Строка 1333 начинает путешествие по карте.
/**
* 一个由原数组每个元素执行回调函数的结果组成的新数组
* Array.prototype.map(callback, thisArg)
*
*/
Array.prototype.mymap = function (callback, thisArg) {
if (this == null) throw new TypeError("this is null or not defined")
let newArr = Object(this)
let len = newArr.length >>> 0
if (typeof callback !== 'function') throw new TypeError(callback + ' is not a function');
let thatArg = arguments.length >= 2 ? arguments[1] : void 0,
resultArr = new Array(len),
mappedValue
for (let i = 0; i < len; i++) {
if (i in newArr) {
// 可能会有疑惑的地方
mappedValue = callback.call(thatArg, newArr[i], i, newArr)
resultArr[i] = mappedValue
}
}
return resultArr
}
Место, где могут быть сомнения, это строка 17. Почему вы можете написать это прямо? Вам не нужно рассматривать случай, что thisArg равен void 0. Я рассматривал это на случай, но подумаем об этом позже, даже если это значение undefined, вы Карта выполняет функцию обратного вызова Это значение функции обратного вызова является окном в нестрогом режиме.
var numbers = [1, 4, 9];
var doubles = numbers.map(function (num) {
console.log(this) // window
return num * 2;
}, void 0);
👆 Когда вы запустите код в консоли, вы обнаружите, что передается thisArg. Когда значение не определено, результатом остается окно. Конечно, оно не определено в строгом режиме. Об этом остается подумать читателю. .
С точки зрения кода нужно обратить внимание:
-
mapне изменяет сам исходный массив, вызвавший его (конечно, вcallbackИзмените исходный массив при выполнении) - Когда функция обратного вызова не возвращает значение, каждое значение последнего нового массива не определено.
-
thisЗначение в конечном счете относительноcallbackНаблюдаемость функции основана наthisПравила, то есть это указывает на проблему - потому что
mapСоздайте новый массив, если вы не собираетесь использовать возвращенный новый массив, но используетеmapпротиворечит первоначальному замыслу дизайна, пожалуйста, используйтеforEachилиfor-ofальтернатива. -
mapОбласть действия метода для обработки элементов массива находится вcallbackМетод определяется перед первым вызовом. передачаmapЭлементы массива, добавленные после метода, не будутcallbackдоступ. Если существующий элемент массива изменился, то передается вcallbackЗначениеmapЗначение при доступе к этому элементу.
reduce
определение:
Выполняет одно из предоставленных вами действий над каждым элементом в массивеreducerФункция (выполняемая в порядке возрастания), которая объединяет свои результаты в одно возвращаемое значение.
грамматика:
let result = array.reduce(callback(accumulator, currentValue, currentIndex, array), initialValue)
параметр:
callback:为数组中每个元素执行的函数,该函数接收一至4个参数
accumulator 累计器
currentValue 当前值
currentIndex 当前索引
array 数组
initialValue
作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。
Применение:
Вариант использования - это простое использование, более продвинутое использование сокращения, в конце есть ссылка на ссылку👇
const arr = [3, 5, 1, 4, 2];
const a = arr.reduce((t, v) => t + v);
// 等同于
const b = arr.reduce((t, v) => t + v, 0);
Посмотрите, как это объясняет gif-анимация👇
Это может быть самый простой способ его использования, давайте распространять свое мнение 😼
// 功能型函数通道
const double = x => x + x;
const triple = x => 3 * x;
const quadruple = x => 4 * x;
// Function composition enabling pipe functionality
const pipe = (...functions) => input => functions.reduce(
(acc, fn) => fn(acc),
input
);
// Composed functions for multiplication of specific values
const multiply6 = pipe(double, triple);
const multiply9 = pipe(triple, triple);
const multiply16 = pipe(quadruple, quadruple);
const multiply24 = pipe(double, triple, quadruple);
// Usage
multiply6(6); // 36
multiply9(9); // 81
multiply16(16); // 256
multiply24(10); // 240
Иногда использование сокращения действительно делает разработку более эффективной✊
Взгляните на array.js в исходном коде v8**.Строка 1505 начинает путь сокращения
/**
* 对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值
* Array.prototype.reduce(callback, initialValue)
*
*/
Array.prototype.myreduce = function (callback /*, initialValue*/ ) {
if (this == null) throw new TypeError("this is null or not defined")
let newArr = Object(this)
let len = newArr.length >>> 0
if (typeof callback !== 'function') throw new TypeError(callback + ' is not a function');
let initialValue,
k = 0
if (arguments.length >= 2) {
initialValue = arguments[1]
} else {
while (k < len && !(k in newArr))
k++
if (k >= len)
throw new TypeError('Reduce of empty array with no initial value')
initialValue = newArr[k++]
}
for (let i = k; i < len; i++) {
if (i in newArr) {
initialValue = callback(initialValue, newArr[i], i, newArr)
}
}
return initialValue
}
С точки зрения кода нужно обратить внимание:
- Когда функция обратного вызова выполняется в первый раз,
accumulatorа такжеcurrentValueЕсть два случая для значения : если вы вызываетеreduce()предоставляется, когдаinitialValue,accumulatorстоимостьinitialValue,currentValueПринимает первое значение в массиве, если не указаноinitialValue,Такaccumulatorвзять первое значение в массиве,currentValueВозьмите второе значение в массиве. - если не предусмотрено
initialValue, reduce выполнит метод обратного вызова, начиная с индекса 1, пропуская первый индекс. если предусмотреноinitialValue, начиная с индекса 0. - если массив пуст и не указан
initialValue, броситTypeError. - Если в массиве только один элемент (независимо от позиции) и нет
initialValue, или предоставитьinitialValueно массив пуст, то будет возвращено это уникальное значение иcallbackвыполняться не будет.
Функция редукции слишком мощная, и те, кому интересно, могут хорошенько на нее взглянуть✊
Конечно, благодаря этому анализу кода, я думаю, вы лучше понимаете принцип сокращения.
reduceRight
Накопить справа налево, аналогично уменьшению, реализация исходного кода будет естественно ✍
определение:
Принимая функцию как одно значение для каждого значения (справа налево) как аккумулятор и массив. Суммируйте результаты как одно возвращаемое значение.
грамматика:
let result = array.reduceRight(callback(accumulator, currentValue, currentIndex, array), initialValue)
параметр:
callback:为数组中每个元素执行的函数,该函数接收一至4个参数
accumulator 上一次调用回调函数时,回调函数返回的值。
currentValue 当前值
currentIndex 当前索引
array 数组
initialValue
首次调用 callback 函数时,累加器 accumulator 的值。如果未提供该初始值,则将使用数组中的最后一个元素,并跳过该元素。
Применение:
Вот разница между сокращением и уменьшением 👏
var a = ['1', '2', '3', '4', '5'];
var left = a.reduce(function(prev, cur) { return prev + cur; });
var right = a.reduceRight(function(prev, cur) { return prev + cur; });
console.log(left); // "12345"
console.log(right); // "54321"
Взгляните на array.js в исходном коде v8**.Строка 1505 начинает путешествие по пути reduceRight.
Если это реализовано, возьмите указательный индекс и смоделируйте от последнего бита массива к началу 😹 Просто обратите внимание на граничное значение
find findIndex
Этот метод был добавлен в спецификацию ECMAScript 6 и может отсутствовать в некоторых реализациях.
определение:
**find:** Возвращает значение первого элемента в массиве, который удовлетворяет предоставленной тестовой функции. в противном случае вернутьсяundefined.
индекс поиска:массив, предоставив первый элемент тестовой функциипоказатель. В противном случае вернуть -1.
грамматика:
let ele = array.find(function(elemnet, index, arr), thisArg)
let eleIndex = array.findIndex(function(elemnet, index, arr), thisArg)
параметр:
Оба грамматически похожи
callback:为数组中每个元素执行的函数,该函数接收一至三个参数
elemnet 数组中正在处理的当前元素
index (可选) 数组中正在处理的当前元素的索引
arr (可选) find方法正在操作的数组
thisArg 可选参数,当执行回调函数callback,用作this值
найти использование:
//寻找数组中的质数
function isPrime(element, index, array) {
var start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) {
return false;
}
}
return element > 1;
}
console.log([4, 6, 8, 12].find(isPrime)); // undefined, not found
console.log([4, 5, 8, 12].find(isPrime)); // 5
Использование findIndex:
//找数组中首个质数元素的索引 不存在素数返回-1
function isPrime(element, index, array) {
var start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) {
return false;
}
}
return element > 1;
}
console.log([4, 6, 8, 12].findIndex(isPrime)); // -1, not found
console.log([4, 6, 7, 12].findIndex(isPrime)); // 2
Взгляните на array.js в исходном коде v8**.1633 линия начинается найти тур
/**
* 返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined
* Array.prototype.find(callback, thisArg)
*
*/
Array.prototype.myfind = function (callback /*, thisArg */ ) {
if (this == null) throw new TypeError("this is null or not defined")
let newArr = Object(this)
let len = newArr.length >>> 0
if (typeof callback !== 'function') throw new TypeError(callback + ' is not a function');
let thatArg = arguments.length >= 2 ? arguments[1] : void 0
for (let i = 0; i < len; i++) {
if (i in newArr && callback.call(thatArg, newArr[i], i, newArr))
return newArr[i]
}
return void 0
}
Принцип работы функции findIndex точно такой же, а возвращаемым значением является просто индекс❗
С точки зрения кода нужно обратить внимание:
- Метод find не изменяет исходный массив
- в первый звонок
callbackфункция будет определять диапазон индексов элементов, поэтому вfindНовые элементы, добавленные в массив после начала выполнения метода, не будутcallbackфункция для доступа. - Если один из массивов не был
callbackЗначение элемента, к которому обращается функция, равноcallbackфункция изменилась, то когдаcallbackКогда функция обращается к нему, его значением будет текущее значение, полученное в соответствии с его индексом в массиве. Доступ к удаленному элементу по-прежнему будет осуществляться, но его возвращаемое значение уже не определено. - Я много читал о функции поиска, и лично я не думаю, что она указана.
thisArgДля параметров указатель this функции обратного вызова не всегда не определен, что более разумно.это соответствует этому правилу указания.
keys & values & entries
определение:
keys()Метод возвращает массив, содержащий каждый ключ индекса в массиве.**Array Iterator**объект.
values()метод возвращает новыйArray Iteratorобъект, который содержит значение для каждого индекса массива
entries()метод возвращает новыйArray IteratorОбъект содержит индекс массива для каждой ключевой / значение-пар.
грамматика:
arr.entries()
Применение:
Использование трех аналогично, давайте возьмем один из них в качестве примера.
const array1 = ['a', 'b', 'c'];
const iterator1 = array1.entries();
const iterator2 = array1.values();
const iterator3 = array1.keys();
console.log(iterator1);
/*Array Iterator {}
__proto__:Array Iterator
next:ƒ next()
Symbol(Symbol.toStringTag):"Array Iterator"
__proto__:Object
*/
iterator.next()
var arr = ["a", "b", "c"];
var iterator = arr.entries();
console.log(iterator.next());
/*{value: Array(2), done: false}
done:false
value:(2) [0, "a"]
__proto__: Object
*/
// iterator.next()返回一个对象,对于有元素的数组,
// 是next{ value: Array(2), done: false };
// next.done 用于指示迭代器是否完成:在每次迭代时进行更新而且都是false,
// 直到迭代器结束done才是true。
// next.value是一个["key","value"]的数组,是返回的迭代器中的元素值。
использоватьдля… изцикл
var arr = ["a", "b", "c"];
var iterator = arr.entries();
// undefined
for (let e of iterator) {
console.log(e);
}
// [0, "a"]
// [1, "b"]
// [2, "c"]
Контента много, надеюсь вы сможете ознакомиться 🉑
Изменить исходный метод массива
splice
определение:
Измените массив, удалив или заменив существующие элементы или добавив новые элементы на место, и верните измененное содержимое в виде массива,Обратите внимание, что этот метод изменит исходный массив
грамматика:
array.splice(start,deleteCount,item1,.....,itemX)
параметр:
start: 指定修改的开始位置(从0计数)
1. 如果超出了数组的长度,则从数组末尾开始添加内容
2. 如果是负值,则表示从数组末位开始的第几位(从-1计数,这意味着-n是倒数第n个元素,并且等价于array.length-n)
3. 如果负数的绝对值大于数组的长度,则表示开始位置为第0位
deleteCount(可选) : 整数,表示要移除的数组元素个数
1. 如果 deleteCount 大于 start 之后的元素的总数,则从 start 后面的元素都将被 删除(含第 start 位)
2. 如果 deleteCount 被省略了,或者它的值大于等于array.length - start(也就是 说,如果它大于或者等于start之后的所有元素的数量),那么start之后数组的所有元素都会被删除。
3. 如果 deleteCount 是 0 或者负数,则不移除元素。这种情况下,至少应添加一个新 元素。
item1, item2, ...(可选)
要添加进数组的元素,从start 位置开始。如果不指定,则 splice() 将只删除数组元素。
Применение:
//从第 2 位开始删除 0 个元素,插入“drum”
var myFish = ["angel", "clown", "mandarin", "sturgeon"];
var removed = myFish.splice(2, 0, "drum");
// 运算后的 myFish: ["angel", "clown", "drum", "mandarin", "sturgeon"]
// 被删除的元素: [], 没有元素被删除
// 从第 2 位开始删除 0 个元素,插入“drum” 和 "guitar"
var removed2 = myFish.splice(2, 0, 'drum', 'guitar');
// 运算后的 myFish: ["angel", "clown", "drum", "guitar", "mandarin", "sturgeon"]
// 被删除的元素: [], 没有元素被删除
Удалить 1 элемент из позиции 2, вставьте «труба»
var myFish = ['angel', 'clown', 'drum', 'sturgeon'];
var removed = myFish.splice(2, 1, "trumpet");
// 运算后的 myFish: ["angel", "clown", "trumpet", "sturgeon"]
// 被删除的元素: ["drum"]
Удалите 2 элемента, начиная с позиции 0, вставьте «попугай», «анемон» и «синий».
var myFish = ['angel', 'clown', 'trumpet', 'sturgeon'];
var removed = myFish.splice(0, 2, 'parrot', 'anemone', 'blue');
// 运算后的 myFish: ["parrot", "anemone", "blue", "trumpet", "sturgeon"]
// 被删除的元素: ["angel", "clown"]
Удалить 1 элемент, начиная со 2-й последней позиции
var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
var removed = myFish.splice(-2, 1);
// 运算后的 myFish: ["angel", "clown", "sturgeon"]
// 被删除的元素: ["mandarin"]
Удалить все элементы, начиная с позиции 2
var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
var removed = myFish.splice(2);
// 运算后的 myFish: ["angel", "clown"]
// 被删除的元素: ["mandarin", "sturgeon"]
Взгляните на array.js в исходном коде v8**.Линия 876 начинает сращивание
Это должна быть простая симуляция, единственное, что раздражает, это граничное значение
sort
определение:
Сортирует элементы массива и возвращает массив,Обратите внимание, что этот метод изменит исходный массив
грамматика:
arr.sort([compareFunction])
параметр:
compareFunction 可选
1. 用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序。
2. 指明了compareFunction,
3. 如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;
4. 如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变。
5. 如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前。
Применение:
var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
return a - b;
});
console.log(numbers);
//也可以写成:
var numbers = [4, 2, 5, 1, 3];
numbers.sort((a, b) => a - b);
console.log(numbers);
// [1, 2, 3, 4, 5]
Вроде персонажей не ASCII
//当排序非 ASCII 字符的字符串(如包含类似 e, é, è, a, ä 等字符的字符串)。
//一些非英语语言的字符串需要使用 String.localeCompare。这个函数可以将函数排序到正确的顺序。
var items = ['réservé', 'premier', 'cliché', 'communiqué', 'café', 'adieu'];
items.sort(function (a, b) {
return a.localeCompare(b);
});
// items is ['adieu', 'café', 'cliché', 'communiqué', 'premier', 'réservé']
Сортировка — это наука, и в ней много содержания, например, сложность события и сложность алгоритма по пространству, которые будут обновлены позже.
pop
определение:
Удаляет последний элемент из массива и возвращает значение этого элемента. Этот метод изменяет длину массива.
грамматика:
arr.pop()
//从数组中删除的元素(当数组为空时返回undefined)。
описывать:
1. pop 方法从一个数组中删除并返回最后一个元素。
2. pop方法根据 length属性来确定最后一个元素的位置。
3. 如果不包含length属性或length属性不能被转成一个数值,会将length置为0,并返回undefined。
4. 如果你在一个空数组上调用 pop(),它返回 undefined。
Применение:
let myFish = ["angel", "clown", "mandarin", "surgeon"];
let popped = myFish.pop();
console.log(myFish);
// ["angel", "clown", "mandarin"]
console.log(popped);
// surgeon
🚀🚀🚀 были
shift
определение:
удалить из массиваПервыйэлемент и возвращает значение этого элемента. Этот метод изменяет длину массива.
грамматика:
arr.shift()
//从数组中删除的元素; 如果数组为空则返回undefined 。
описывать:
1. shift 方法移除索引为 0 的元素(即第一个元素),并返回被移除的元素,其他元素的索引值随之减 1
2. 如果 length 属性的值为 0 (长度为 0),则返回 undefined。
3. shift 方法并不局限于数组:这个方法能够通过 call 或 apply 方法作用于类似数组的对象上
4. 对于没有 length 属性(从0开始的一系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何意义。
Применение:
let myFish = ['angel', 'clown', 'mandarin', 'surgeon'];
console.log('调用 shift 之前: ' + myFish);
// "调用 shift 之前: angel,clown,mandarin,surgeon"
var shifted = myFish.shift();
console.log('调用 shift 之后: ' + myFish);
// "调用 shift 之后: clown,mandarin,surgeon"
console.log('被删除的元素: ' + shifted);
// "被删除的元素: angel"
🚀🚀🚀 Не должно быть сложностей
unshift
определение:
Добавить один или несколько элементов в массивначалои возвращает массивновая длина (т.метод изменения исходного массива
грамматика:
arr.unshift(element1, ..., elementN)
// element要添加到数组开头的元素或多个元素。
описывать:
1. unshift 方法会在调用它的类数组对象的开始位置插入给定的参数。
2. unshift 特意被设计成具有通用性;这个方法能够通过 call 或 apply 方法作用于类数组对象上
3. 不过对于没有 length 属性(代表从0开始的一系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何意义。
4. 注意, 如果传入多个参数,它们会被以块的形式插入到对象的开始位置,它们的顺序和被作为参数传入时的顺序一致
5. ,传入多个参数调用一次 unshift ,和传入一个参数调用多次 unshift (例如,循环调用),它们将得到不同的结果。例如:
Применение:
let arr = [4,5,6];
arr.unshift(1,2,3);
console.log(arr); // [1, 2, 3, 4, 5, 6]
arr = [4,5,6]; // 重置数组
arr.unshift(1);
arr.unshift(2);
arr.unshift(3);
console.log(arr); // [3, 2, 1, 4, 5, 6]
см. другой пример
arr.unshift(0); // result of the call is 3, which is the new array length
// arr is [0, 1, 2]
arr.unshift(-2, -1); // the new array length is 5
// arr is [-2, -1, 0, 1, 2]
arr.unshift([-4, -3]); // the new array length is 6
// arr is [[-4, -3], -2, -1, 0, 1, 2]
arr.unshift([-7, -6], [-5]); // the new array length is 8
// arr is [ [-7, -6], [-5], [-4, -3], -2, -1, 0, 1, 2 ]
🚀🚀🚀 Не должно быть сложностей
push
определение:
Добавляет один или несколько элементов в конец массива и возвращает новую длину массива.
грамматика:
arr.push(element1, ..., elementN)
// element要添加到数组末尾的元素或多个元素。
// 放回值:当调用该方法时,新的 length 属性值将被返回。
описывать:
1. push 方法具有通用性。该方法和 call() 或 apply() 一起使用时,可应用在类似数组的对象上。
2. push 方法根据 length 属性来决定从哪里开始插入给定的值。
3. 如果 length 不能被转成一个数值,则插入的元素索引为 0,包括 length 不存在时。当 length 不存在时,将会创建它。
Применение:
добавить элемент в массив
var sports = ["soccer", "baseball"];
var total = sports.push("football", "swimming");
console.log(sports);
// ["soccer", "baseball", "football", "swimming"]
console.log(total);
// 4
Используйте объекты, такие как массивы
var obj = {
length: 0,
addElem: function addElem (elem) {
// obj.length is automatically incremented
// every time an element is added.
[].push.call(this, elem);
}
};
// Let's add some empty objects just to illustrate.
obj.addElem({});
obj.addElem({});
console.log(obj.length);
// → 2
//注意,尽管 obj 不是数组,但是 push 方法成功地使 obj 的 length 属性增长了,就像我们处理一个实际的数组一样。
Поехали, сложностей в уходе за ней возникнуть не должно🚀🚀🚀
reverse
определение:
Меняет местами элементы в массиве и возвращает массив. Первый элемент массива становится последним, а последний элемент массива становится первым. Этот метод изменяет исходный массив.
грамматика:
arr.reverse()
// 放回值:颠倒后的数组
описывать:
1. reverse 方法颠倒数组中元素的位置,改变了数组,并返回该数组的引用。
2. reverse方法是特意类化的;此方法可被 called 或 applied于类似数组对象。
3. 对象如果不包含反映一系列连续的、基于零的数值属性中的最后一个长度的属性,则该对象可能不会以任何有意义的方式运行。
Применение:
Обратные элементы в массиве
const a = [1, 2, 3];
console.log(a); // [1, 2, 3]
a.reverse();
console.log(a); // [3, 2, 1]
Обратные элементы в массиве, подобном массиву
onst a = {0: 1, 1: 2, 2: 3, length: 3};
console.log(a); // {0: 1, 1: 2, 2: 3, length: 3}
Array.prototype.reverse.call(a); //same syntax for using apply()
console.log(a); // {0: 3, 1: 2, 2: 1, length: 3}
copyWithin
определение:
Поверхностно копирует часть массива в другое место в том же массиве и возвращает его без изменения длины исходного массива.
грамматика:
array.copyWithin(target, start = 0, end = this.length)
// 放回值:改变后的数组。
параметр:
target
1. 0 为基底的索引,复制序列到该位置。如果是负数,target 将从末尾开始计算。
2. 如果 target 大于等于 arr.length,将会不发生拷贝。如果 target 在 start 之后,复制的序列将被修改以符合 arr.length。
start
1. 0 为基底的索引,开始复制元素的起始位置。如果是负数,start 将从末尾开始计算。
2. 如果 start 被忽略,copyWithin 将会从0开始复制。
end
1. 0 为基底的索引,开始复制元素的结束位置。copyWithin 将会拷贝到该位置,但不包括 end 这个位置的元素。如果是负数, end 将从末尾开始计算。
2. 如果 end 被忽略,copyWithin 方法将会一直复制至数组结尾(默认为 arr.length)。
Уведомление:
1. 参数 target、start 和 end 必须为整数。
2. 如果 start 为负,则其指定的索引位置等同于 length+start,length 为数组的长度。end 也是如此。
3. copyWithin 是一个可变方法,它不会改变 this 的长度 length,但是会改变 this 本身的内容,且需要时会创建新的属性。
Применение:
const a = [1, 2, 3];
[1, 2, 3, 4, 5].copyWithin(-2)
// [1, 2, 3, 1, 2]
[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]
[1, 2, 3, 4, 5].copyWithin(-2, -3, -1)
// [1, 2, 3, 3, 4]
[].copyWithin.call({length: 5, 3: 1}, 0, 3);
// {0: 1, 3: 1, length: 5}
console.log(a); // [1, 2, 3]
a.reverse();
console.log(a); // [3, 2, 1]
Я не могу использовать этот метод для решения проблемы, у меня от этого голова болит❌
fill
определение:
Заполняет все элементы массива от начального до конечного индекса фиксированным значением. Индекс завершения не включен.
грамматика:
arr.fill(value, start, end )
// 放回值:修改后的数组。
параметр:
value
1. 用来填充数组元素的值。
start (可选)
1. 起始索引,默认值为0。
end (可选)
1. 终止索引,默认值为 this.length。
описывать:
1. 如果 start 是个负数, 则开始索引会被自动计算成为 length+start,其中 length 是 this 对象的 length 属性值
2. fill 方法故意被设计成通用方法, 该方法不要求 this 是数组对象。
3. fill 方法是个可变方法, 它会改变调用它的 this 对象本身, 然后返回它, 而并不是返回一个副本。
4. 当一个对象被传递给 fill方法的时候, 填充数组的是这个对象的引用。
Применение:
[1, 2, 3].fill(4); // [4, 4, 4]
[1, 2, 3].fill(4, 1); // [1, 4, 4]
[1, 2, 3].fill(4, 1, 2); // [1, 4, 3]
[1, 2, 3].fill(4, 1, 1); // [1, 2, 3]
[1, 2, 3].fill(4, 3, 3); // [1, 2, 3]
[1, 2, 3].fill(4, -3, -2); // [4, 2, 3]
[1, 2, 3].fill(4, NaN, NaN); // [1, 2, 3]
[1, 2, 3].fill(4, 3, 5); // [1, 2, 3]
Array(3).fill(4); // [4, 4, 4]
[].fill.call({ length: 3 }, 4); // {0: 4, 1: 4, 2: 4, length: 3}
// Objects by reference.
var arr = Array(3).fill({}) // [{}, {}, {}];
// 需要注意如果fill的参数为引用类型,会导致都执行都一个引用类型
// 如 arr[0] === arr[1] 为true
arr[0].hi = "hi"; // [{ hi: "hi" }, { hi: "hi" }, { hi: "hi" }]
Взгляните на array.js в исходном коде v8.Линия 1700 начинает заправку
if (!Array.prototype.fill) {
Object.defineProperty(Array.prototype, 'fill', {
value: function(value) {
// Steps 1-2.
if (this == null) {
throw new TypeError('this is null or not defined');
}
var O = Object(this);
// Steps 3-5.
var len = O.length >>> 0;
// Steps 6-7.
var start = arguments[1];
var relativeStart = start >> 0;
// Step 8.
var k = relativeStart < 0 ?
Math.max(len + relativeStart, 0) :
Math.min(relativeStart, len);
// Steps 9-10.
var end = arguments[2];
var relativeEnd = end === undefined ?
len : end >> 0;
// Step 11.
var final = relativeEnd < 0 ?
Math.max(len + relativeEnd, 0) :
Math.min(relativeEnd, len);
// Step 12.
while (k < final) {
O[k] = value;
k++;
}
// Step 13.
return O;
}
});
}
После четырех часов кодинга я не могу это кодировать ✍✍✍, посмотрите на чужой стандартный текст, отпустите меня😭
не изменяет исходный метод массива
slice
определение:
Возвращает новый объект массива, которыйbeginа такжеendОпределяется исходным массивоммелкая копия(включатьbegin, исключаяend). Исходный массив не будет изменен.
Для глубокого и мелкого копирования вы можете увидеть мою статьюКак написать удовлетворительный глубокий текст на собеседовании (подходит для младшего фронтенда)
грамматика:
arr.slice([begin[, end]])
параметр:
begin (可选)
1. 提取起始处的索引(从 0 开始),从该索引开始提取原数组元素。
2. 如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取
3. slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)
4. 如果省略 begin,则 slice 从索引 0 开始。
5. 如果 begin 大于原数组的长度,则会返回空数组。
end (可选)
1. slice(1,4) 会提取原数组中从第二个元素开始一直到第四个元素的所有元素 (索引为 1, 2, 3的元素)
2. 如果该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取。
3. 如果 end 被省略,则 slice 会一直提取到原数组末尾。
4. 如果 end 大于数组的长度,slice 也会一直提取到原数组末尾。
Применение:
Возвращает часть существующего массива
var fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango'];
var citrus = fruits.slice(1, 3);
// fruits contains ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango']
// citrus contains ['Orange','Lemon']
Когда в массиве есть значение ссылочного типа, поверхностная копия является адресом ссылочного типа.
// 使用 slice 方法从 myCar 中创建一个 newCar。
var myHonda = { color: 'red', wheels: 4, engine: { cylinders: 4, size: 2.2 } };
var myCar = [myHonda, 2, "cherry condition", "purchased 1997"];
var newCar = myCar.slice(0, 2);
newCar[0].color = 'blue';
console.log(myHonda.color) // bule
Массивоподобный объект преобразуется в массив
function list() {
return Array.prototype.slice.call(arguments);
}
var list1 = list(1, 2, 3); // [1, 2, 3]
//你也可以简单的使用 [].slice.call(arguments) 来代替
Взгляните на array.js в исходном коде v8.Строка 762 начинает путешествие по слайсу
(function () {
'use strict';
var _slice = Array.prototype.slice;
try {
// Can't be used with DOM elements in IE < 9
_slice.call(document.documentElement);
} catch (e) { // Fails in IE < 9
// This will work for genuine arrays, array-like objects,
// NamedNodeMap (attributes, entities, notations),
// NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes),
// and will not fail on other DOM objects (as do DOM elements in IE < 9)
Array.prototype.slice = function(begin, end) {
// IE < 9 gets unhappy with an undefined end argument
end = (typeof end !== 'undefined') ? end : this.length;
// For native Array objects, we use the native slice function
if (Object.prototype.toString.call(this) === '[object Array]'){
return _slice.call(this, begin, end);
}
// For array like object we handle it ourselves.
var i, cloned = [],
size, len = this.length;
// Handle negative value for "begin"
var start = begin || 0;
start = (start >= 0) ? start : Math.max(0, len + start);
// Handle negative value for "end"
var upTo = (typeof end == 'number') ? Math.min(end, len) : len;
if (end < 0) {
upTo = len + end;
}
// Actual expected size of the slice
size = upTo - start;
if (size > 0) {
cloned = new Array(size);
if (this.charAt) {
for (i = 0; i < size; i++) {
cloned[i] = this.charAt(start + i);
}
} else {
for (i = 0; i < size; i++) {
cloned[i] = this[start + i];
}
}
}
return cloned;
};
}
}());
Я думаю, что это больше процесс моделирования, и единственное, что немного сложно понять, это определение граничного значения, поэтому я нашел код под спецификацией, вы можете обратиться к нему.
С точки зрения кода нужно обратить внимание:
- Если вы хотите его использовать, просто посмотрите главу о параметрах 🈯
- Что касается проблемы глубокого и поверхностного копирования, если элемент является ссылкой на объект (а не фактическим объектом),
sliceскопирует ссылку на объект в новый массив. Обе ссылки на объекты ссылаются на один и тот же объект. Если объект, на который делается ссылка, изменяется, этот элемент в новом и исходном массивах также изменяется. - Если в любой из двух массивов добавить новый элемент, это не повлияет на другой.
- Для глубокого и поверхностного копирования вы можете прочитать эту статьюКак написать удовлетворительный глубокий текст на собеседовании (подходит для младшего фронтенда)
join
определение:
массив (илимассивоподобный объект) объединяет все элементы в строку и возвращает эту строку. Если в массиве только один элемент, то этот элемент возвращается без разделителя.
грамматика:
arr.join(separator)
параметр:
separator (可选)
指定一个字符串来分隔数组的每个元素。
如果需要,将分隔符转换为字符串。
如果缺省该值,数组元素用逗号(,)分隔。
如果separator是空字符串(""),则所有元素之间都没有任何字符。
Применение:
Объедините элементы массива, используя четыре разных разделителя
var a = ['Wind', 'Rain', 'Fire'];
var myVar1 = a.join(); // myVar1的值变为"Wind,Rain,Fire"
var myVar2 = a.join(', '); // myVar2的值变为"Wind, Rain, Fire"
var myVar3 = a.join(' + '); // myVar3的值变为"Wind + Rain + Fire"
var myVar4 = a.join(''); // myVar4的值变为"WindRainFire"
объединять массивоподобные объекты
function f(a, b, c) {
var s = Array.prototype.join.call(arguments);
console.log(s); // '1,a,true'
}
f(1, 'a', true);
Взгляните на array.js в исходном коде v8.Строка 468 начинает путь соединения
Для обновления идея состоит в том, чтобы удалить каждый элемент массива или объекта, подобного массиву, и, наконец, завершить объединение строк с помощью разделителя.
toString
определение:
Возвращает строку, представляющую указанный массив и его элементы.
грамматика:
arr.toString()
Когда массив используется в качестве текстового значения или выполняется операция конкатенации строк, егоtoStringметод.
Применение:
const array1 = [1, 2, 'a', '1a'];
console.log(array1.toString());
// expected output: "1,2,a,1a"
concat
определение:
Используется для объединения двух или более массивов. Этот метод не изменяет существующий массив, а возвращает новый массив.
грамматика:
var newArr =oldArray.concat(arrayX,arrayX,......,arrayX)
параметр:
arrayx(可选)
将数组和/或值连接成新数组。
如果省略了valueN参数参数,则concat会返回一个它所调用的已存在的数组的浅拷贝。
Применение:
Следующий код объединяет два массива в новый массив:
var alpha = ['a', 'b', 'c'];
var numeric = [1, 2, 3];
alpha.concat(numeric);
// result in ['a', 'b', 'c', 1, 2, 3]
объединить три массива
var num1 = [1, 2, 3],
num2 = [4, 5, 6],
num3 = [7, 8, 9];
var nums = num1.concat(num2, num3);
console.log(nums);
// results in [1, 2, 3, 4, 5, 6, 7, 8, 9]
объединить значения в массив
var alpha = ['a', 'b', 'c'];
var alphaNumeric = alpha.concat(1, [2, 3]);
console.log(alphaNumeric);
// results in ['a', 'b', 'c', 1, 2, 3]
Уведомление:
-
concatметод не меняетсяthisили любой массив, предоставленный в качестве аргумента, вместо этого возвращает поверхностную копию -
concatСкопируйте ссылку на объект в новый массив. И исходный массив, и новый массив относятся к одному и тому же объекту. То есть, если указанный объект изменен, изменения видны как для нового массива, так и для исходного массива. Сюда входят элементы, которые также являются параметрами массива. - Массивы/значения сохраняются при конкатенации. Кроме того, любая операция над новым массивом (только если элемент не является ссылкой на объект) не влияет на исходный массив, и наоборот.
indexOf
определение:
Возвращает первый индекс в массиве, по которому можно найти данный элемент, или -1, если он не существует.
грамматика:
array.indexOf(searchElement,fromIndex)
параметр:
searchElement (必选) 要查找的元素
fromIndex
1. 开始查找的位置。如果该索引值大于或等于数组长度,意味着不会在数组里查找,返回-1。
2. 如果参数中提供的索引值是一个负值,则将其作为数组末尾的一个抵消,即-1表示从最后一个元素开始查找
3. 注意:如果参数中提供的索引值是一个负值,并不改变其查找顺序,查找顺序仍然是从前向后查询数组。如果抵消后的索引值仍小于0,则整个数组都将会被查询。其默认值为0.
4. 采用的是严格等于 ===
Применение:
Метод indexOf определяет положение нескольких значений в массиве
var array = [2, 5, 9];
array.indexOf(2); // 0
array.indexOf(7); // -1
array.indexOf(9, 2); // 2
array.indexOf(2, -1); // -1
array.indexOf(2, -3); // 0
Найти все вхождения указанного элемента
var indices = [];
var array = ['a', 'b', 'a', 'c', 'a', 'd'];
var element = 'a';
var idx = array.indexOf(element);
while (idx != -1) {
indices.push(idx);
idx = array.indexOf(element, idx + 1);
}
console.log(indices);
// [0, 2, 4]
indexOf() не распознаетNaN
let a = ['啦啦', 2, 4, 24, NaN]
console.log(a.indexOf('啦')); // -1
console.log(a.indexOf(NaN)); // -1
console.log(a.indexOf('啦啦')); // 0
Взгляните на array.js в исходном коде v8.Строка 1411 начинает путешествие indexOf.
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(searchElement, fromIndex) {
var k;
// 1. Let O be the result of calling ToObject passing
// the this value as the argument.
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
var O = Object(this);
// 2. Let lenValue be the result of calling the Get
// internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If len is 0, return -1.
if (len === 0) {
return -1;
}
// 5. If argument fromIndex was passed let n be
// ToInteger(fromIndex); else let n be 0.
var n = +fromIndex || 0;
if (Math.abs(n) === Infinity) {
n = 0;
}
// 6. If n >= len, return -1.
if (n >= len) {
return -1;
}
// 7. If n >= 0, then Let k be n.
// 8. Else, n<0, Let k be len - abs(n).
// If k is less than 0, then let k be 0.
k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
// 9. Repeat, while k < len
while (k < len) {
if (k in O && O[k] === searchElement) {
return k;
}
k++;
}
return -1;
};
}
Это стандартный код, можете на него ссылаться, писать не буду, мне на свидание, времени нет 🙏
lastIndexOf
определение:
Возвращает индекс последнего указанного элемента (то есть допустимого значения или переменной JavaScript) в массиве или -1, если он не существует. Поиск вперед с конца массива, начиная сfromIndexначать с.
грамматика:
arr.lastIndexOf(searchElement,fromIndex)
параметр:
searchElement (必选) 要查找的元素
fromIndex
1. 从此位置开始逆向查找
2. 默认为数组的长度减 1(arr.length - 1),即整个数组都被查找
3. 如果该值大于或等于数组的长度,则整个数组会被查找。如果为负值,将其视为从数组末尾向前的偏移
4. 即使该值为负,数组仍然会被从后向前查找。如果该值为负时,其绝对值大于数组长度,则方法返回 -1,即数组不会被查找。
Применение:
Индекс последнего вхождения этого элемента в массив или -1, если он не найден.
var array = [2, 5, 9, 2];
var index = array.lastIndexOf(2);
// index is 3
index = array.lastIndexOf(7);
// index is -1
index = array.lastIndexOf(2, 3);
// index is 3
index = array.lastIndexOf(2, 2);
// index is 0
index = array.lastIndexOf(2, -2);
// index is 0
index = array.lastIndexOf(2, -1);
// index is 3
Посмотрим как реализован последний indexOf🤳, времени нет.
Суммировать
Я хочу плакать, но нет слез🤥, мне понадобился день + код, чтобы завершить эти знания массива JS, и нашел"1,2 Вт слово"👍👍👍 Многие определения заимствованы с официального сайта, в основном из-за боязни ввести в заблуждение многих фронтенд-персонала, таких же элементарных, как я, поэтому используются стандартные термины официального сайта.
Если код сложный, я написал его сам и многому научился.
"Если вам это нравится, вы можете поставить лайк 👍👍👍 / подписаться, поддержать, я надеюсь, вы сможете прочитать эту статью и получить что-то"
Ссылаться на
25 расширенных способов использования массива, которые вы должны знать
9 основных операций связанного списка "алгоритмы и структуры данных"