предисловие
Я пишу вопросы по программированию по интервью недавно. Я часто пользуюсь массивами и часто хочу быть ленивым. Я использую методы, предоставляемые им, но я все еще нефессию в использовании методов массива, что приводит к написанию много мусора. Простой, Эффективный и элегантный 👊
Итак, ✍Эта статья основана на понимании характеристик массивов 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 основных операций связанного списка "алгоритмы и структуры данных"