предисловие
Популяризируйте JavaScript, раскройте тайну JavaScript и проникните в самое сердце JavaScript. Эта серия статей подходит для чтения каждому.
Содержание этой статьи:
- Нормализация массива.
- Массивы и контейнеры массивов.
- Array API объясняется в спецификации ECMAScript.
- Если вы хотите использовать Array, но не хотите изучать API.
- Расширения Array API, не входящие в стандартную спецификацию.
- Обработка и оптимизация массива движком V8.
- Природа данных.
Будучи единственной сложной структурой данных в языке JavaScript, кроме Object, Array очень необходим для тщательного освоения.
Первоначальная цель этой статьи — объяснить концепцию, функции, все API и удобное использование массива и массива в JavaScript. В конце концов, вы можете достичь мастерства, найти наиболее правильное среди бесчисленных применений и сделать операции с массивами удобными.
Когда г-н Цянь закончил писать эту статью, это был уже конец 2019 года. На момент завершения статьи это последниеСпецификация ECMAScript,Массив в JavaScript v8,Массив в C++ V8,Время выполнения массива V8.
Советы: Поскольку длина статьи слишком велика, я думаю, вы с меньшей вероятностью будете придерживаться чтения. Рекомендуется первый сбор. Если вы не читали содержимое или не хотите его видеть, вы можете выполнить ускоренную перемотку вперед или выборочный просмотр.
Стандартные массивы: четыре вопроса души — вопросы из источника массивов
Лучший способ чему-то научитьсяПостоянно забрасывая вопросами, через исследование проблемы, шаг за шагом, чтобы рассеять туман и найти истину.
Приведенное выше предложение было написано Учителем Цянем и не является авторитетным. Итак, г-н Цянь сначала задал вопрос, чтобы доказать правильность этой точки зрения.
Насколько важно задавать вопросы? Это проблема. Здесь Учитель Цянь использует известные высказывания нескольких великих богов, чтобы объяснить эту проблему:
Творение начинается с проблемы, только когда есть проблема, мы можем думать, а когда мы думаем, есть решение проблемы, и только тогда мы можем найти независимый способ мышления. —— Тао Синчжи
Правильный вопрос часто является ответом на большинство проблем. - Гейзенберг
Мудрость жизни, наверное, в том, чтобы каждый раз спрашивать почему. - Бальзак
Первым признаком культурного ума является способность задавать вопросы. - Плеханов
Мудрый человек, который всегда будет задавать вопросы. —— Учитель Цянь, известный программист
Те, кто умеет задавать вопросы, подобны нападению на укрепленный лес.Те, кого легко изменить, сначала, потом программу. —— «Книга обрядов · Сюэцзи»
Если вы будете задавать вопросы, вы будете богаты, а если вы будете использовать это сами, вы будете малы. - «Книга истории: письмо Чжунсе»
Чуткий и прилежный, не стыдящийся задавать вопросы. —— «Аналекты Конфуция, Гонье Чанг»
Учиться джентльмену должно быть легко, а просить и учиться идут рука об руку. Если вы не учитесь, вы не можете породить сомнения; если вы не спрашиваете, вы не можете получить широкое знание. - Лю Кай
Вопрос знания — вопрос научный, и здесь не должно быть лицемерия и гордыни, а скорее наоборот — честности и смирения. - Председатель Мао
Что ж, г-н Цянь только что разобрался и разобрал десять причин, почему этот вопрос важен Даже великий лидер-основатель Председатель Мао любит вопросы, и это очень хорошо. Но это статья, объясняющая программу, а не статья об изучении известных высказываний и афоризмов, так что ее примут все. Достаточно понять, что «учиться на задачах очень эффективно». Перейдите к теме ниже.
1. Что такое массив?
Теперь Учитель Цянь первым задает первый формальный вопрос:Какой к черту массив?
Этот вопрос кажется простым, но так ли это на самом деле? Если вы не удовлетворены, вы можете сначала указать свой ответ, а после прочтения этой статьи снова сравнить его, чтобы увидеть, соответствует ли он исходному ответу.
Здесь г-н Цянь поленился и достал объяснение массива из Википедии:
Структура данных массива (англ. Array Data Structure), аббревиатура массив (англ. array), представляет собой структуру данных, состоящую из набора элементов одного типа (Element), выделяющую непрерывную память для хранения. Адрес хранения, соответствующий элементу, может быть вычислен с использованием индекса элемента.
Из этого очень официального объяснения г-н Цянь обнаружил несколько ключевых моментов:однотипные элементы, непрерывная память, индексы.
Стандартные массивы должны соответствовать трем указанным выше условиям. На самом деле есть еще одно условие, которое не отражено в вики, т.е.исправленный размер.
Дизайн массива, первый - с языка C. Позже, в котором появляется язык программирования, следуйте примеру большей части дизайна массива языка C. Такие, как C ++, Java, Go и так далее.
Отсюда г-н Цянь разрушит концепцию массивов JavaScript в вашем традиционном мышлении. Только свержение может отменить проверку. Только расставшись, мы можем воссоединиться.
2. Почему у массивов есть типы?
Возьмем в качестве примера стандартные массивы Java. Зачем брать Java в качестве примера? Потому что в JavaScript нет «стандартного массива».
int arr[] = new int[3]; /*创建一个长度为3的int类型数组*/
arr[0] = 1; // 给下标0 赋值
arr[1] = 2; // 给下标1 赋值
arr[2] = 3; // 给下标2 赋值
Давайте рассмотрим немного общих операций в JavaScript на Java.
arr[2] = "3"; // error: incompatible types: String cannot be converted to int
Смотри, Java действительно сообщил об ошибке! Эта ошибка означает: Массивы типа int несовместимы с элементами типа String.
Если вы работали с JavaScript и никаким другим строго типизированным языком программирования, вы должны подумать, что это потрясающе. Могут ли массивы вообще иметь типы? Быстро задайте второй вопрос:Почему у массивов есть типы?
Да, у массивов есть типы, и есть причины, по которым массивы имеют типы, Учитель Цянь расскажет о том, почему у массивов есть типы позже.
3. Почему нельзя изменить длину массива?
Еще одна общая операция JavaScript.
arr[3] = 1;// Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
Java снова сообщил об ошибке! Если вы использовали JavaScript, вы, вероятно, были ошеломлены, увидев это. Эта ошибка означает: индекс превышает максимальные границы массива.
Это явление указывает на другую проблему: однажды определенная длина массива не изменится.
Учитель Цянь задаст вам третий вопрос:Почему нельзя изменить длину массива?
Увидев это, вы наверняка подумаете, что с таким количеством ограничений на стандартные массивы пользоваться им слишком хлопотно, не так ли?
4. Почему индекс массива начинается с 0?
Наконец, Учитель Цянь добавил вопрос, к которому все привыкли и даже игнорировали:Почему индекс массива начинается с 0?
Время ответа
Второй вопрос: почему тип массива?
Из-за формулы адресации массива:array[i]Address = headAddress + i * dataTypeSize
Что такое формула адресации?
Режим адресации — это способ, с помощью которого процессор находит эффективный адрес в соответствии с адресной информацией, указанной в инструкции, а также метод определения адреса данных этой инструкции и адреса следующей выполняемой инструкции.
Позвольте мне перевести это, как найти эту переменную в блоке памяти.
Это требует некоторого знания компьютерных принципов, структур данных и алгоритмов.Поскольку основное содержание этой статьи состоит в том, чтобы объяснить знание Array в JavaScript, г-н Цянь не будет подробно останавливаться на этих вопросах. Однако, учитывая, что многие люди не имеют высшего образования или серьезно не изучали принципы работы компьютера. Учитель Цянь еще немного рассказывает о том, что такое адресация и для чего она полезна.
Прежде всего, что такое адрес памяти? Адрес памяти выглядит так:0x12345678. В языках программирования созданные нами переменные сохраняются в памяти, вас можно понимать какhashили в ECMAScriptobject,0x12345678даkey, вы создаете имя переменной, и значение переменной равноvalue. А адресация заключается в том, чтобы найти адрес памяти, поместить адрес памяти вvalueвыньте это. заменитьJavaScriptВыражение выглядит так:Memory["0x12345678"].
Наверное, понимаю адресацию. Далее рассмотрим процесс создания массива:
Чтобы создать массив, нужно подать заявку на место фиксированного размера в памяти. Насколько велико это пространство? Он получается в соответствии с длиной массива и типом данных массива.
Как в примере выше. Тип int занимает 4 байта, а массив типа int длиной 3 требует 3*4=12 байт памяти.
После успешного выполнения приложения ЦП заблокирует это пространство. И запишите первый адрес памяти этого пространства. Это headAddress приведенной выше формулы.
При последующих посещениях эту формулу можно использовать для быстрого решения.
Это объясняет, почему массивы имеют типы.
Вопрос 3: Почему нельзя изменить длину массива?
Поскольку память массива выделяется непрерывно, если длина массива изменяется, это означает, что объем памяти, занимаемый массивом, также изменяется. Пространство за исходным пространством массива может быть занято другими значениями, что также из соображений безопасности, поэтому его нельзя изменить.
Вопрос 4: Почему индекс массива начинается с 0?
Если индекс начинается с 1, это очень ценно с точки зрения логики человеческого десятичного числа, но для ЦП это проблематично. Формула адресации массива должна быть изменена на:array[i]Address = headAddress + (i-1) * dataTypeSize, чтобы каждый раз при работе с массивом ЦП без причины выполнял еще одну операцию вычитания, что пагубно сказывается на производительности.
Увидев это, вы должны понимать, что тип Array, который мы ежедневно используем в JavaScript, не является «стандартным массивом». В то же время я также понимаю характеристики нормализованных массивов.
Массив контейнеров: анализируем ArrayList в Java и ECMAScript в Array
Я полагаю, что благодаря приведенным выше четырем вопросам и ответам вы также понимаете сложность проектирования массивов. Нам действительно трудно что-либо сказать, но мы должны.
Контейнер массива для маскировки деталей
Если вы продолжите программировать с таким количеством ограничений на массивы, многие люди сойдут с ума. Поэтому умные программисты изобрели контейнер массива, который защищает базовые операции массива.
Например, ArrayList, который очень часто появляется в Java. То же самое верно и для типа Array в ECMAScript.
В чем преимущества таких контейнеров?
Давайте сделаем это и испытаем это.
Возьмите Java в качестве примера. Зачем вообще брать Java в качестве примера? Потому что только сравнение может пробудить ваше глубокое мышление.
ArrayList arr = new ArrayList(1);// 创建一个初始长度为 1 的数组
arr.add(1);// 加 1 个数据
arr.add("2");// 再加 1 个 String 类型的数据
System.out.println(arr);// 没有问题,正常输出 [1, 2]
Вы видите, что ArrayList в Java решает две важные проблемы.
1. Может хранить различные типы данных.
2. Он может быть автоматически расширен.
Так как же это достигается? Это содержание выходит за рамки данной статьи. Но Учитель Цянь не мог не сказать это коротко.
1. Как добиться того, чтобы можно было хранить разные типы данных?
Будь то JavaScript или Java, основная память делится на кучную память Head и стековую память Stack. Из-за основных типов данных (извините, что прерываю, учитель Цянь задал здесь вопрос? Сколько основных типов данных в ECMAScript в 2019 году?) все они хранятся в памяти стека. Почему он должен храниться в памяти стека? Это еще один хороший вопрос. Вы можете предположить. Поскольку базовые типы данных являются фиксированными значениями, поскольку значения являются фиксированными, размер также является фиксированным. Говоря об этом, г-н Цянь задаст еще один вопрос: в ECMAScript сколько байтов занимает трехсимвольная переменная String? Видите ли, ** проблемы есть везде, это зависит от того, есть ли у вас глаза, чтобы найти проблему. **Это тоже маленькая пасхалка: до ECMAScript2015 в ECMAScript5.0 использовалась кодировка Unicode, и как китайские иероглифы, так и английские иероглифы занимали по 2 байта. Итак, ответ на поставленный выше вопрос: 2*3=6 байт. Но после ECMAScript6 ответ будет другим. Поскольку кодировка была изменена, она была изменена на utf8. Вот еще вопрос, чем отличается юникод от утф8? Эй, он вот-вот рухнет? utf8 кодируется с использованием длины от 1 до 4 байтов. Поскольку иностранцы обнаружили, что большинство веб-сайтов в мире на английском языке, в то время как веб-сайты на других языках (в глазах иностранцев, помимо английского, другие языки в совокупности называются другими языками) составляют очень маленький. Поэтому в utf8 английские символы занимают всего 1 байт, а другие языки, например китайский, занимают 3 байта. Следовательно, в приведенном выше вопросе по-прежнему отсутствует условие, и необходимо уточнить, на каком языке 3 символа, чтобы дать правильный ответ. Мы зашли слишком далеко, так что давайте быстро вернемся назад и продолжим разговор о кучах и стеках. Поскольку размер основных типов данных фиксирован, полезно знать общий размер массива в стеке, и вы можете подать заявку на непрерывный блок памяти. Так что же делает ECMAScript при сохранении переменной ссылочного типа? Вы, должно быть, шустро догадались, то есть он хранится в памяти кучи. Чтобы быть точным, данные переменной хранятся в памяти кучи, а память стека по-прежнему будет хранить одну вещь, то есть указатель памяти памяти кучи, который мы часто называем ссылкой. Это объясняет, как контейнеры массива хранят разные типы данных.
Подробное введение памяти кучи и памяти стека не будет обсуждаться.
Если вы хотите узнать больше об этой части, рекомендуется прочитатьРасширенное программирование с помощью JavaScript (3-е издание)Глава четвертая.
Эта часть стековой памяти не является концепцией, которую можно изучить в одиночку. Ученикам с плохой базой рекомендуется читать »Глубокое понимание компьютерных систем (оригинальная книга, 3-е издание)". Книга имеет высокий балл 9,8 на Douban. Но на самом деле это не книга, которая является «углубленной» в традиционном смысле. Это книга, которая объясняет общий контекст «нижней части компьютера». Так что это очень широкая книга, очень подходящая для совершенствования системы знаний о персональном компьютере.
2. Как реализовать автоматическое расширение?
ArrayList создается без параметров и по умолчанию создает массив емкостью 10. Каждый раз, когда элемент добавляется, он будет проверять, достаточно ли емкости, и если нет, внутри будет создан новый массив, и емкость массива будет в 1,5 раза больше емкости исходного массива. Затем переместите данные из исходного массива в новый массив. Если емкости нового массива по-прежнему недостаточно, сразу будет создан массив нужной емкости.
В этом нет большой проблемы, самая большая проблема заключается в том, что в определенной степени это повлияет на производительность. Еще одна проблема, не имеющая никакого отношения к JavaScript, — это вопросы безопасности потоков. Из-за создания новых массивов процесс переноса данных занимает определенное время. В многопоточном языке, таком как Java, если другой поток обращается к ArrayList во время этого процесса, возникает проблема.
Зачем объяснять ArrayList в Java? Поскольку г-н Цянь видел только исходный код реализации ArrayList, это очень смущает. Студенты, которые не читали JavaScript, если вам интересно, вы можете перейти по ссылке на исходный код V8, которую я дал в начале статьи, чтобы увидеть, как это делает ECMAScript. Я предполагаю, что его реализация такая же, как ArrayList.После прочтения вы можете вернуться и сказать г-ну Цянь, чтобы посмотреть, правильно ли г-н Цянь угадал. Хотя г-н Цянь не рассматривал реализацию V8 внимательно, пожалуйста, не подвергайте сомнению знания г-на Цяня в JavaScript и не делайте случайных предположений, что г-н Цянь занимается Java. Я хотел бы подчеркнуть здесь, что г-н Цянь является серьезным программистом JavaScript и всегда использовал JavaScript в качестве первого языка программирования. О нет, теперь это TypeScript.
Будь то Java JDK или ECMAScript V8, в конечном счете реализация все равно остается на C. Поэтому Учитель Цянь советует всем: не думайте слишком много, чтобы увидеть исходный код C.
Подводя итог: все, что программисту неприятно использовать, всегда будет трансформироваться по-разному. Пока не станет тем, что нравится всем. Если вы хотите полностью понять что-то, вы должны начать с первоисточника, посмотреть на ее первоначальный вид, затем посмотреть на весь процесс ее макияжа и пластической хирургии, и, наконец, увидеть, как она шаг за шагом превращается в бабочку.
Суть массива в EAMCAScript, что такое массив?
Это самый распространенный массив в JavaScript.
let arr = [
"h",
9,
true,
null,
undefined,
_ => _,
{ a: "b" },
[1, 2],
Symbol(1),
2n ** 1n,
Infinity,
NaN,
globalThis,
Error("hi"),
Math.LN10,
Date(),
/\w+/i,
new Map([["k1", "v1"]]),
new Set([1, 2]),
new DataView(new ArrayBuffer(16)),
new Promise((resolve, reject) => {}),
];
Немного сумбурно, но безобидно. Как видите, массив похож на гигантскую черную дыру, которая может содержать что угодно в ECMAScript. Подойдут переменные, данные любого типа, включая сам массив. Это напоминает мне рекламу игр, которые часто появляются в пространстве QQ, классика гор и морей, Кун, пожирающий мир и всемогущий.
Почему это возможно?
Поскольку, как описано выше,Когда Array хранит примитивные типы, он сохраняет значения. Когда вы сохраняете ссылочный тип, вы сохраняете ссылку на память.
Массивы в ECMAScript не похожи на традиционные массивы. Потому что это объект.
Поскольку ECMAScript является языком со слабой типизацией, в нем нет обязательных ограничений системы типов, и любой тип переменной может быть присоединен к любому свойству. Массивы не исключение.
Добавьте свойство к объекту.
let obj = {};
obj["0"] = 1;
Добавить элемент в массив.
let arr = [];
arr["0"] = 1;
Получить значение от объекта.
obj["0"];
Получить значения из массива.
arr["0"];
Другой пример, следующий массив:
["dog", "pig", "cat"];
Эквивалентно следующим объектам:
{
"0": "dog",
"1": "pig",
"2": "cat",
"length": 3
}
В какой-то степени Array и Object не слишком отличаются. Даже если говорить радикально,Массив и объект по сути одно и то же.(Учитель Цянь не несет никакой юридической ответственности за это предложение, просто произносит его вскользь)
В JavaScript вы можете думать о массиве как о реализации объекта более высокого порядка.
Насколько свободен Array в JavaScript? Значения разных типов могут быть сохранены, доступны по отрицательным индексам, индексированы за рамками исходного объявления и даже по нечисловым индексам. Хотя Array несовместим с массивами, он все равно называется массивом, ведь он все еще похож на массивы, например, Array все еще в"0"как начальный индекс. (Это холодная шутка.)
Итак, прекратите использовать традиционные концепции массивов для определения массивов ECMAScript. Потому что это просто длинное изображение.
Hardcore Battle: Array API в ECMAScript
О чем следует говорить и чего не следует говорить, о чем следует спрашивать и чего не следует спрашивать, сказано выше.
Далее, давайте перейдем к последней части этой статьи и почувствуем мощь Array из всех API.
До того, как г-н Цянь написал эту статью, многие люди написали подобные превосходные статьи, такие какMDN
Тем не менее, Учитель Цянь гарантирует, что это более яркое, легкое для понимания, полное юмора и уникальное, чем то, что говорят эти люди. Погрузит вас глубоко... в мир Array.
Хотя эта статья появляется очень поздно, нет никакого способа. Учитель Цянь считает, что обратные волны могут ударить передние волны о пляж и сильно их опустошить.
В текущей стандартной спецификации все свойства и методы Array в сумме дают 36, что действительно смущает.
Начнем с создания массива шаг за шагом.
создать массив
Тайна творения, как тьма ночная, велика. И призрак знания есть не что иное, как вещь утра. - Тагор
Существует 3 основных и стандартных способа создания массива.
1. Создайте напрямую, используя literal[]
let arr1 = [0, 1, 2];
2. Используйте конструктор Array для создания
let arr1 = new Array(0, 1, 2);
3. Вызовите встроенный метод Array для создания
let arr1 = Array(0, 1, 2);
Сходства и различия:
Метод 2 и метод 3 работают одинаково, поскольку указатель this оценивается внутри реализации функции массива.
new Arrayа такжеArrayЕсть два варианта использования: когда передается только 1 параметр, вместо массива, хранящего значение, создается неопределенный элемент со значением количества параметров.
let arr1 = [10]; // [10]
let arr2 = Array(10); // [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]
Существуют также нетрадиционные и нестандартные способы создания массивов. Конкретные типы тысяч учителей не учитывались, потому что это не очень важно. Наиболее распространенное нестандартное и нестандартное использованиеfrom, никаких спойлеров, можете продолжать смотреть вниз.
массив доступа
Истина — это жизнь, и вы не должны искать ее в своей голове. --Ромен Роллан
Поговорив о создании массива, давайте посмотрим, как получить к нему доступ.
Доступ к массиву на самом деле довольно прост, с помощью квадратных скобок[]Вот и все.
let arr1 = [0, 1, 2];
arr1[0]; // 0
Мы привыкли писатьnumberПараметр типа заключен в квадратные скобки, потому что мы знаем, что число — это нижний индекс массива элемента, а нижний индекс массива — это индекс.numberЗначение типа нормальное, верно? Но на самом деле это не так, в приведенном выше примереarr1[0]При фактическом выполнении он станетarr1['0']. пройдет черезtoStringМетоды неявно преобразуются. Почему это так? потому чтоECMAScriptВ спецификации указано. Давайте сначала продадим его здесь, давайте пока не будем об этом говорить, заинтересованные студенты могут проверить это сами. Хотя будет неявный процесс преобразования, обычные программисты не будут напрямую использовать кавычки.
свойства экземпляра
constructor
Без отца, без матери, без матери? - «Книга песен»
В ECMAScript почти все, кроме null и undefined, имеет это свойство. Указывает, кто сконструировал объект.
Сцена, в которой это свойство обычно используется, заключается в том, чтобы определить, является ли объект экземпляром Array.
let arr = [];
arr.constructor === Array; // true
Но, к сожалению, это свойство доступно для записи. Доступность для записи означает, что этот метод не на 100% определяет, является ли объект экземпляром массива или нет.
let arr = [];
arr.constructor = String;
arr.constructor === Array; // false
arr.constructor === String; // true
Видите ли, переменная ARR, которая была изначально создана путем массива, изменяется на строку в качестве родителя через одну строку кода. Еще раз, было подтверждено, что экземпляры массива - это все о деньгах, являющихся отцом, и молоко является матерью.
Посмотрите на другой пример.
let str = "";
str.constructor = Array;
str.constructor === Array; // false
str.constructor === String; // true
Существует резкая разница между str и arr. str — послушный сын, биологический отец — биологический отец, и неважно, есть ли у тебя деньги.
На самом деле, помимо String, можно изменить свойства конструктора еще нескольких базовых типов, но это изменение не имеет никакого эффекта.
Почему это не сработало? Потому что это включает в себя распаковку.
Итак, вопрос от учителя:Почему примитивные типы могут вызывать методы и обращаться к свойствам?
Если вы понимаете этот вопрос, вы сможете понять, почему вышеуказанное явление. Это не пункт знаний массива, а расширение знаний.
Вы ответите на вопрос выше, Учитель Цянь задаст другой вопрос,В чем разница между примитивными типами, созданными с помощью конструкторов, и примитивными типами, созданными с помощью литералов?
length
У каждого есть свои сильные и слабые стороны
Представляет количество элементов массива.
let arr = [0, 1, 2];
arr.length; // 3
Это свойство кажется очень простым, тут и говорить не о чем, правда?
На самом деле, есть кое-что, что я могу вам сказать.
lengthВеличайший магический эффект заключается в прямом измененииlengthАтрибуты могут удалять элементы или добавлять элементы.
let arr = [0, 1, 2];
arr.length = 2;
console.log(arr); // [0, 1]
arr.length = 5;
console.log(arr); // [0, 1, empty × 3]
Смотрите здесь, еще одинempty, что это? Вы знаете?
emptyэто иundefinedОчень похоже, но с небольшой разницей.
Можно провести эксперимент.
console.log(arr[3] === undefined); // true
В этом эксперименте мы нашлиemptyвсе равноundefinedиз.
Но некоторые различия у них все же есть. Например, следующий эксперимент.
arr.indexOf(undefined); // -1
arr.filter(item => item === undefined); // []
arr.forEach(item => {
console.log(item);
}); // 1, 2
indexOf,filterа такжеforEachне думайemptyравныйundefinedиз. будет автоматически игнорироватьсяempty.
Проведите еще два эксперимента.
arr.includes(undefined); // true
arr.map(item => typeof item); // ["number", "number", empty × 3]
ноincludesУдивительно думатьemptyесть иundefinedконцепция. пока вmap, он автоматически сохранитсяemptyпустой слот.
Это не значитtypeofне хорошо, ноtypeof itemЭто предложение при встречеemptyКогда он пропускается напрямую, он не выполняется.
Для того, чтобы доказать это, возьмем всемогущегоtypeofоператор для проведения эксперимента.
console.log(typeof arr[3]); // undefined
Что, черт возьми, здесь происходит? Учитель Цянь обнаружил в документе ECMAScript6, что в нем четко указано, чтоemptyравноundefinedДа, к этому надо относиться в любом случаеempty. Г-н Цянь еще раз просмотрел исходный код V8 и, конечно же, нашел соответствующую информацию в исходном коде V8.emptyОписание оказывается пустой ссылкой на объект.
пустая ссылка на объектКакого типа должна быть эта штука в ECMAScript? В ECMAScript всего несколько типов, и само собой разумеется, что он не соответствует ни одному типу.
ни за что,undefinedЭтот неудобный тип данных стал необъяснимо и обидноemptyсторонник.
метод
from
Ученые должны быть смелыми и пройти долгий путь
От ECMAScript1 была проблема с головной болью (конечно, головной боли гораздо больше, чем одна, я сказал, что здесь есть одна, я не говорю, что только одна, здесь вы должны напомнить об этом.), Ecmascript переполнен большим количеством Объект номер класса. Они похожи на массивы, но не являются массивами. Топ самых типичныхargumentsобъект иgetElementsByTagName.
Чтобы решить эту проблему, многие библиотеки классов имеют свои собственные решения, такие как знаменитая библиотека JavaScript Overlord древней эпохи.jQuery, естьmakeArrayСюда.
С постоянно меняющейся технологической эволюцией, благодаря тяжелой работе и самоотверженности бесчисленных энтузиастов JavaScript, он пережил более 20 лет превратностей. Наконец-то появился ECMAScriptfromЭто собственный супер API. С этим API ECMAScript больше не должен быть похож наmakeArrayТакие сторонние решения. ECMAScript встает! Говоря об этом, г-н Цянь не мог не думать о тех великих богах, которые пролили свою кровь за свободу, открытость, расширение и интеграцию ECMAScript.Именно они встали, когда ECMAScript был унижен, и спасли Ли Миньюй от гибели. прилив страдания. Во время разработки ECMAScript г-н Цянь увидел, что разработчики ECMAScript отваживаются смотреть в лицо безрадостной жизни и капающей крови.Java,C,C++,четноеPHPПод всеобщим презрением, в оскорблении «Разве это не скриптовый язык?» у всех на устах, мы зажгли будущее пылающей страстью и кровью, сконденсировавшейся в духовный факел.
Оттащили, берем обратно. Так много дует, торопитесь и продолжайте учитьсяfromИспользуй это.
Роль: создать новый массив из массивоподобного объекта или итерируемого объекта.
грамматика:Array.from(arrayLike[, mapFn[, thisArg]])
параметр:
-
arrayLike: объект псевдомассива или итерируемый объект, который вы хотите преобразовать в массив. -
**
mapFn**(необязательно): Если этот параметр указан, функция обратного вызова будет выполняться для каждого элемента в новом массиве. -
**
thisArg**(необязательно): выполнить функцию обратного вызоваmapFnВремяthisобъект.
Возвращаемое значение: новый экземпляр массива.
Поддерживаются такие типы, как String, Set, Map, arguments.
Также поддерживается создание через функции.
// String 转 Array
let arr1 = Array.from("123"); // ["1", "2", "3"]
// Set 转 Array
let arr2 = Array.from(new Set([1, 2, 3])); // [1, 2, 3]
// Map 转 Array
let arr3 = Array.from(
new Map([
[1, 1],
[2, 2],
[3, 3],
])
); // [[1, 1], [2, 2], [3, 3]]
// MapKey 转 Array
let arr4 = Array.from(
new Map([
[1, 1],
[2, 2],
[3, 3],
]).keys()
); // [1, 2, 3]
// MapValue 转 Array
let arr5 = Array.from(
new Map([
[1, 1],
[2, 2],
[3, 3],
]).values()
); // [1, 2, 3]
// arguments 转 Array
function fn() {
return Array.from(arguments);
}
fn(1, 2, 3); // [1, 2, 3]
Помимо роли преобразования, программисты, которые любят исследовать, нашли несколько других магических применений.
1. Используется для создания массива.
let arr = Array.from({ length: 3 });
console.log(arr); // [undefined, undefined, undefined]
fromМетод хороший и не создает 3emptyпублично заявить. Похоже, спецификация ECMAScript6 все еще очень хороша, по крайней мере, Chrome к нему прислушивается.
Вы также можете добавить сюда некоторую логику, например, создание массива чисел в диапазоне.
let arr = Array.from({ length: 3 }, (item, index) => index);
console.log(arr); // [0, 1, 2]
2. Мелко скопируйте массив.
let arr = [1, 2, 3];
let arr2 = Array.from(arr);
3. Глубоко скопируйте массив.
На основе массивов неглубоких копий в сочетании с Array.isArray. Принцип прост.
function arrayDeepClone(arr) {
return Array.isArray(arr) ? Array.from(arr, arrayDeepClone()) : arr;
}
Говоря об этом, г-н Цянь задал вопрос:В ECMAScript есть несколько методов глубокого и мелкого копирования массивов, в чем их преимущества и недостатки и какие сценарии применения подходят?
В дополнение к этим методам существует множество других замечательных применений в других сценариях, которые здесь не перечислены. во всяком случаеfromЭтот API очень гибкий, и студенты, которые любят исследовать, могут попробовать больше самостоятельно.
isArray
Когда ложь есть истина, истина есть ложь, а когда истина есть ложь, ложь есть истина.
Роль: используется для определения того, является ли переменная объектом массива.
грамматика:Array.isArray(obj)
параметр:
-
obj: Значение для обнаружения.
Возвращаемое значение: если значениеArray, истина, иначе ложь.
Возвращает логическое значение.
let arr = [];
Array.isArray(arr); // true
Есть два других распространенных способа определить, является ли переменная массивом.
1. Используйтеinstanceof.
let arr = [];
arr instanceof Array; // true
instanceofПринцип достигается через цепочку прототипов. То есть оценивается, есть ли правый прототип в цепочке прототипов левого объекта. Вот вопрос:Как это сделать вручнуюinstanceof?
2. Используйтеconstructor.
let arr = [];
arr2.constructor === Array; // true
constructorСвойство содержит метод конструктора при создании экземпляра, но это свойство можно изменить.
3. ИспользуйтеObject.prototype.toString.call
let arr = [];
Object.prototype.toString.call(arr); // "[object Array]"
Object.prototype.toString.call()Обычно используется для оценки встроенных объектов в ECMAScript. Но этот метод можно переопределить.
这几种方法各有弊端。 Но в целомНастоятельно рекомендуется прямое использованиеArray.isArray. Потому чтоiFrameсередина,instanceofа такжеconstructorне удастся. а такжеObject.prototype.toStringЭтот метод слишком сложен.
Здесь г-н Цянь добавил, что возвращаемые значения этих методов могут быть подделаны. Поэтому, когда иногда код не оправдывает ожиданий, не слишком доверяйте своим глазам, больше используйте свой мозг.
Ниже приводится метод фальсификации, но не меняйте его в своих собственных проектах в свободное время, провинциальный руководитель К.
let arr = [];
Array.isArray = () => false;
Array.isArray(arr); // false
let arr2 = [];
arr2.__proto__ = Object;
arr2 instanceof Array; // false
let arr3 = [];
arr3.constructor = String;
arr3.constructor === Array; // false
let arr4 = [];
Object.prototype.toString = () => "object";
Object.prototype.toString.call(arr4); // "object"
of
Разница на миллиметр, а погрешность на тысячу миль. - «Хань Шу»
Вот еще один шлак из начала проектирования Array, потому что использованиеnew ArrayилиArrayПри создании массива таким образом он будет вести себя по-разному в зависимости от количества и типа параметров. вести тебяникогда не доступенnew Arrayсоздать массив только с одним числовым типом. Преувеличивать,ofЕсть только одна причина появления метода, очень чистого и очень реалистичного, чтобы создать массив только с одним числовым типом. **Преимущество этого заключается в унификации поведения при создании массивов.
Роль: используется для создания нового экземпляра массива с переменным количеством параметров, независимо от количества или типа параметров.
грамматика:Array.of(element0[, element1[, ...[, elementN]]])
Возвращаемое значение: вновь созданный экземпляр массива.
let arr = Array.of(10); // [10]
в основном используется для различенияArrayпройти 1numberВ случае параметров типа. Это обязательно создаст массив с элементами, равными первому параметру.
Вы должны использовать его при создании массива в будущемArrayПри построении метода используйтеofметод замены является хорошим решением.
Методы модификации экземпляра
изменит значение самого массива.
copyWithin
Заблудился на восток, собрал шелковицу. - «Книга династии Поздняя Хань»
Невозможно найти API с очень низким смыслом существования, и даже сценариев применения, что является так называемым сверхдизайном.
Роль: неглубокое копирование части массива в другую позицию в массиве и возврат его без изменения длины массива.
грамматика:arr.copyWithin(target[, start[, end]])
параметр:
- target: Нижний индекс целевой позиции, в которую нужно переместиться
- start: необязательный, начальный индекс, значение по умолчанию 0.
-
end: необязательный, завершающий индекс (исключая этот элемент), по умолчанию
arr.length.
Возвращаемое значение: измененный массив.
let arr1 = [0, 1, 2, 3, 4];
let result = arr1.copyWithin(1, 2, 4); // 截取下标 2-4 的元素,插入到下标 1 的位置
console.log(arr1); // [0, 2, 3, 3, 4]
console.log(result); // [0, 2, 3, 3, 4]
fill
Если вы не наберете несколько шагов, вы не сможете пройти тысячу миль; если вы не наберете небольшой ручей, вы не сможете создать реку или море. - "Сюньцзы"
присутствие иcopyWithinТакой же.
Функция: Заменить значения всех элементов в указанном диапазоне в массиве на фиксированное значение.
грамматика:arr.fill(value[, start[, end]])
параметр:
- value: значение, используемое для заполнения элементов массива.
- start: необязательный, начальный индекс, значение по умолчанию 0.
-
end: необязательный, завершающий индекс (исключая этот элемент), по умолчанию
arr.length.
Возвращаемое значение: измененный массив.
let arr = [0, 1, 2, 3];
let result = arr.fill(1, 2, 3);
console.log(arr); // [0, 1, 1, 3]
console.log(result); // [0, 1, 1, 3]
pop
Джентльмены любят удачу по-своему. - "Аналекты"
popВдохновение исходит из стека. На самом деле это одна из стандартных операций стека, а также самая основная операция.popа такжеpushПара хороших братьев, которые любят и убивают друг друга.
Функция: удалить последний элемент массива и вернуть этот элемент.
грамматика:arr.pop()
Возвращаемое значение: элемент, удаленный из массива (возвращается, когда массив пуст).undefined).
const arr1 = [1, 2, 3];
const result = arr1.pop();
console.log(arr1); // [1, 2]
console.log(result); // [1, 2]
popПоскольку это самая старая и основная операция, здесь не так уж много наворотов.
push
Море открыто сотням рек, и терпимость велика; стена стоит тысячи миль, и нет желания быть непреклонным. —— Линь Цзэсюй
так какpopБрат-близнец , напоминает мне поговорку о том, что любойpushдано,popВсе забрать.
Функция: добавить элемент в конец массива и вернуть длину массива после операции.
Параметры: элемент, добавляемый в конец массива.
грамматика:arr.push(element1, ..., elementN)
Возвращаемое значение: новоеlengthстоимость имущества.
let arr = [1, 2, 3];
let result = arr.push(5, 6, 7);
console.log(arr); // [1, 2, 3, 5, 6, 7]
console.log(result); // 4
popФункция обратной операции , также является старым API, и операция также очень проста.
reverse
Три тысячи славы, пыли и земли, восемь тысяч миль облаков и луны. ——Юэ Фэй
Функция: изменить порядок расположения элементов в массиве на обратный, то есть исходный первый становится последним, а исходный последний становится первым.
грамматика:arr.reverse()
Возвращаемое значение: измененный массив.
const arr = [1, 2, 3];
const result = arr.reverse();
console.log(arr); // [3, 2, 1]
console.log(result); // [3, 2, 1]
reverseОбращение строки может быть достигнуто с помощью некоторых других API.
let str = "hello,world!";
str
.split()
.reverse("")
.join(""); // "!dlrow,olleh"
shift
Вычеркни любой момент из моей жизни, и я не смогу быть тем, кто я есть сегодня. - Акутагава Рюноскэ
shiftа такжеpopЭффект тот же, ноpopзаключается в удалении последнего элемента массива.
Функция: удалить первый элемент из массива и вернуть значение этого элемента. Этот метод изменяет длину массива.
грамматика:arr.shift()
Возвращаемое значение: элемент, удаленный из массива; возвращается, если массив пуст.undefined.
const arr1 = [1, 2, 3];
const result = arr1.shift();
console.log(arr1); // [2, 3]
console.log(result); // 1
sort
Человек есть результат его собственных действий, и ничего больше. - Сартр
Роль: использовать настраиваемый алгоритм для сортировки элементов массива. Порядок сортировки по умолчанию создается, когда элементы преобразуются в строки, а затем сравниваются на предмет их последовательности значений единиц кода UTF-16.
грамматика:arr.sort([compareFunction])
параметр:
compareFunction([firstEl, secondEl]): необязательный, используется для указания функции сортировки в определенном порядке. Если этот параметр опущен, элементы сортируются по локусу Unicode каждого символа преобразованной строки.
firstEl: Первый элемент, используемый для сравнения.
secondEl: Второй элемент для сравнения.
Возвращаемое значение: отсортированный массив.
const arr1 = [1, 9, 9, 8, 0, 8, 0, 7];
const result = arr1.sort((x, y) => x - y);
console.log(arr1); // [0, 0, 1, 7, 8, 8, 9, 9]
console.log(result); // [0, 0, 1, 7, 8, 8, 9, 9]
Производительность сортировки зависит от пользовательской функции. и запуск двигателя. Учитель Цянь изучил реальность базового движка, но обнаружил, что реализация каждого движка отличается, поэтому один и тот же код работает на разных платформах, и скорость будет разной.
splice
Воля и судьба часто идут вразрез друг с другом, и решимость в конце концов будет ниспровергнута. - Шекспир
Функция: изменить массив, удалив или заменив существующие элементы или добавив новые элементы на место, и вернуть измененное содержимое в виде массива. Этот метод изменяет исходный массив.
грамматика:array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
параметр:
start: Указывает начальную позицию для модификации (считая с 0). Если оно превышает длину массива, добавить содержимое с конца массива; если отрицательное, то означает бит с конца массива (считая от -1, что означает -n — n-й последний элемент и т. д.) вarray.length-n); если абсолютное значение отрицательного числа больше длины массива, это означает, что начальная позиция — 0-й бит.
deleteCount: необязательный, целое число, указывающее количество удаляемых элементов массива. еслиdeleteCountбольше, чемstartПосле общего количества элементов, затем изstartСледующие элементы будут удалены (включая первыйstartбиты). еслиdeleteCountУдалено, или его значение больше или равноarray.length - start(то есть, если он больше или равенstartколичество всех элементов после), тоstartПосле этого все элементы массива удаляются. еслиdeleteCountравен 0 или отрицателен, ни один элемент не удаляется. В этом случае необходимо добавить хотя бы один новый элемент.
item1, item2, ...: необязательный элемент, добавляемый в массив, изstartлокация начинается. Если не указано, тоsplice()удалит только элементы массива.
spliceозначает вырезание и методы доступаsliceРазница всего в одно слово, но разница не в полторы звезды.sliceЭто означает ломтик. Многие люди часто путают эти два понятия. Я видел, как иностранец сказал хороший способ отличить память,spliceэто дополнительноеp, значениеProduces Side Effects(с побочными эффектами). Подобно этому типу API с похожими именами, но очень разными, ECMAScript не только является такой парой, например, есть также строкиsubstrа такжеsubstring.
spliceИспользование очень много и разнообразно. Но в конечном счете всего 4 операции.
операция усечения
Просто сосредоточьтесь на первом параметре. Когда передается только один параметр, это означает усечение.spliceможет иlengthтакже обрезать массив.
let array = [0, 1, 2, 3];
array.splice(3);
// 执行结果等同于 array.length = 3;
операция вставки
Просто обратите внимание на 1-й параметр и 3-й параметр. Первый параметр указывает, с чего начать вставку, а третий параметр указывает, какой элемент вставлять. Второй параметр устанавливается равным0представляет операцию вставки.
let array = [0, 1, 2, 3];
array.splice(1, 0, "1"); // 从下标为1的地方插入元素 '1'
console.log(array); // [0, "1", 1, 2, 3]
удалить операцию
Просто обратите внимание на 1-й параметр и 2-й параметр. 1-й параметр означает удаление оттуда, а 2-й параметр означает удаление нескольких элементов.
let array = [0, 1, 2, 3];
array.splice(1, 1); // 从下标为1的地方删除1个元素
console.log(array); // [0, 2, 3]
операции удаления и вставки
Эта операция требует внимания ко всем параметрам, как было сказано ранее.
const arr = [1, 2, 3];
const result = arr.splice(1, 2, 10, 11); // 从下标1的位置,删除2个元素,并加入元素 10 和 11
console.log(arr); // [1, 10, 11]
console.log(result); // [2, 3]
требует внимания,spliceОтрицательные индексы также поддерживаются.
let array = [0, 1, 2, 3];
array.splice(-2, 1, 1, 2, 3); // [0, 1, 1, 2, 3, 3]
unshift
Спросите, как канал может быть таким чистым, ведь там есть источник живой воды. - Чжу Си
Роль: добавить один или несколько элементов в массивначалои возвращает массивновая длина.
грамматика:arr.unshift(element1, ..., elementN)
Список аргументов: элемент или элементы, добавляемые в начало массива.
Возвращаемое значение: возвращает добавленное значение массиваlengthстоимость имущества.
Нечего сказать,shiftантоним ,pushхороший брат.
const arr = [1, 2, 3];
const result = arr.unshift(5);
console.log(arr); // [5, 1, 2, 3]
console.log(result); // 4
массивоподобный объект
Объекты с характеристиками массива — это подобные массиву объекты, также известные какArrayLike.
Из второй части, «Контейнеры массивов», мы узнали, что в JavaScript операции с массивами и массивоподобными объектами очень похожи. На самом деле, есть более интересный момент: мы можем не только манипулировать объектами как массивами, но и использовать методы массивов для работы с объектами.
let obj = {
push: function(el) {
return [].push.call(this, el);
},
};
obj.push(2);
console.log(obj);
/**
[object Object] {
0: 2,
length: 1,
push: function(el){ return [].push.call(this, el);}
}
**/
можно увидеть,pushавтоматически добавит0свойства иlengthАтрибуты.
Проведите еще один эксперимент.
let obj = {
0: 0,
push: function(el) {
return [].push.call(this, el);
},
};
obj.push(2);
console.log(obj);
ОбнаружитьpushПосле этого исходное свойство0заменил на 2.
Этоpushправило:pushметод согласноlengthсвойство, чтобы решить, где начать вставку данного значения. еслиlengthне может быть преобразовано в значение, индекс вставленного элемента равен 0, в том числеlengthкогда нет. когдаlengthКогда его нет, он будет создан.
Посмотрите нижеlengthситуация есть.
let obj = {
0: 0,
length: 10,
push: function(el) {
return [].push.call(this, el);
},
};
obj.push(2);
console.log(obj);
/**
[object Object] {
0: 0,
10: 2,
length: 11,
push: function(el) { return [].push.call(this, el);}
}
**/
можно увидетьlengthСвойства выполняются+1операции, и он считает, что в массиве уже 10 элементов, то вновь добавленные 2 будут 11-м элементом с индексом 10.pushТакой глупый, да, он был таким глупым.
И его брат,popимеет иpushтакое же поведение. Я не буду расширять демонстрацию здесь, вы можете попробовать сами с расширением объекта.
Такое поведение называется鸭子类型. Так что же такое утиная печать?
утиный тип(Английский:duck typing)существуетпрограммированиесредний дадинамический типстиль.在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前методи совокупность определенных свойств. Концепция получила свое название отДжеймс Уиткомб РайлиПредложенныйутиный тест(Смотри ниже "историяглаву), «утиный тест» можно выразить следующим образом:
«Когда вы видите птицу, которая ходит, как утка, плавает, как утка, и крякает, как утка, тогда эту птицу можно назвать уткой».
Другими словами, в ECMAScript объектами, которые выглядят как массивы, можно управлять с помощью методов массива. Это не ограничивается толькоpupа такжеpushДва метода, многие другие могут быть применены к этому набору правил.
метод доступа к экземпляру
Значение самого массива не изменится, будет возвращено новое значение.
concat
Успех здания — не кусок дерева, увлажнение моря — не первоклассная отдача. -- "Записи династии Восточная Чжоу"
Роль: объединить два или более массивов. Этот метод не изменяет существующий массив, а возвращает новый массив.
грамматика:var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])
параметр:value*N*необязательный
Объединить массивы и/или значения в новый массив. если опущеноvalueNпараметр параметр, затемconcatвернет неглубокую копию существующего массива, для которого он был вызван.
Возвращаемое значение: новый экземпляр массива.
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const result = arr1.concat(arr2, 7, "8", [9]);
console.log(result); // [1, 2, 3, 4, 5, 6, 7, "8", [9]]
concatВ основном следует отметить 2 момента. Пункт 1, конкатенировать можно все, не обязательно массивы, как в примере выше.
Второй моментconcatОперация представляет собой неглубокую копию следующим образом.
const arr1 = [1, 2, 3];
const obj = { k1: "v1" };
const arr2 = [[4]];
const result = arr1.concat(obj, arr2);
console.log(result); // [1, 2, 3,{ k1: "v1" }, [4]]
obj.k2 = "v2";
arr2[0].push(5);
console.log(result); // [1, 2, 3,{ k1: "v1", k2: "v2" }, [4, 5]]
includes
Нет прекращения жизни, нет конца, нет продолжения, нет нет и нет существования? —— «Разговор о небе, солнце и троих» Сун Инсин.
Функция: Определить, содержит ли массив указанное значение.В зависимости от ситуации, если он содержит, он вернет true, иначе он вернет false.
грамматика:arr.includes(valueToFind[, fromIndex])
параметр:
valueToFind: Необязательно, значение элемента для поиска. Если не пройдено, вернитесь напрямуюfalse.
fromIndex: необязательно, отfromIndexначать поиск по индексуvalueToFind. Если отрицательный, в порядке возрастания отarray.length + fromIndexindex, чтобы начать поиск (даже если пропустить впередfromIndexиндекс абсолютного значения , а затем выполнить поиск в обратном направлении). По умолчанию 0.
Возвращаемое значение: логическое значение, указывающее, существует ли элемент.
const arr1 = [1, 2, 3];
const result = arr1.includes(1);
console.log(result); // true
const result2 = arr1.includes(22);
console.log(result2); // false
Примечание. Ссылочный тип литерала нельзя оценить, можно оценить только базовый тип и ссылку.
const t = [1];
const arr1 = [t, 2, 3];
const result = arr1.includes(t);
console.log(result); // true
const result2 = arr1.includes([1]);
console.log(result2); // false
includesродился в EMAScript6. Уже в EMAScript5 всем нравится использоватьindexOfРавен ли он-1чтобы определить, существует ли элемент в массиве. Когда-то в отрасли был аналогичный сторонний API под названиемcontains. Итак, поскольку это новый API, и он делает что-то похожее на существующий API, должна быть причина.
Сначала рассмотрим общую операцию.
const arr = [1, 2, 3];
console.log(arr.indexOf(2) !== -1); // true
console.log(arr.includes(2)); // true
Вроде нет проблем?
Тогда давайте посмотрим на необычную операцию.
const arr = [NaN];
console.log(arr.indexOf(NaN) !== -1); // false
console.log(arr.includes(NaN)); // true
Разница есть!indexOfобычно не совпадаетNaN, поскольку в ECMAScriptNaN === NaNРезультатfalse.
Давайте посмотрим на другой пример.
const arr = [, , , ,];
console.log(arr.indexOf(undefined) !== -1); // false
console.log(arr.includes(undefined)); // true
Эти двое, наверноеincludesа такжеindexOfСамая большая разница.
join
В то время в маленьком пруду не было воды, и не было проблем с волонгами на мелководье. —— Доу Вэй, «Раздача талисманов в пьяном виде»
Функция: объединяет все элементы массива в строку и возвращает строку. Если в массиве только один элемент, то этот элемент возвращается без разделителя.
грамматика:arr.join([separator])
параметр:
separator: Необязательно, укажите строку для разделения каждого элемента массива. При необходимости преобразуйте разделитель в строку. Если это значение установлено по умолчанию, элементы массива отмечаются запятыми (,) разделены. еслиseparatorэто пустая строка (""), между всеми элементами нет символов.
Возвращаемое значение: строка, объединяющая все элементы массива. еслиarr.length0 возвращает пустую строку.
const arr = [1, 2, 3];
const result = arr.join();
console.log(result); // "1,2,3"
joinи строкаsplitЭффект почти обратный.
joinПри использовании необходимо обращать внимание, сначала будет вызываться каждый элементtoStringСращивание снова. Элемент, подобный пустому массиву, преобразуется в строку."", так что смысла существования при сращивании нет.
let arr = ["h", 9, true, null, [], {}];
let result = arr.join("|");
console.log(result); // "h|9|true|||[object Object]"
Конечно, вы можете активно переопределить егоtoStringметод, результат будет другим.
let arr = ["h", 9, true, null, [], {}];
[].__proto__.toString = function() {
return "Array";
};
let result = arr.join("|");
console.log(result); // "h|9|true||Array|[object Object]"
И если он существует в массиве, его можно преобразовать вStringэлемент, возникает исключение. НапримерSymbol.
let arr = ["h", 9, true, null, Symbol(1)];
arr.join("|"); // TypeError: Cannot convert a Symbol value to a string
slice
Человек, осмеливающийся потратить впустую даже час времени, показывает, что он еще не умеет ценить всю ценность жизни. - Дарвин
Функция: Возьмите сегмент из массива, чтобы сформировать новый массив. Получает 2 параметра, первый — это индекс начального элемента, а второй — индекс конечного элемента (исключая этот элемент).
грамматика:arr.slice([begin[, end]])
параметр:
begin: необязательный, по умолчанию 0, индекс, с которого извлекается начало.
end: необязательный, по умолчанию массивlength. Извлеките индекс в конце. (Включатьbegin, не содержитend)
Возвращаемое значение: новый массив, содержащий извлеченный элемент.
const arr1 = [1, 2, 3];
const result = arr1.slice(1, 2); // 从下标1的位置,截取到下标2
console.log(result); // [2]
Специальное использование:
slice()Массивы можно копировать поверхностно.
const result = arr1.slice();
toSource
Когда книга готова к использованию, я ненавижу меньше, и я не знаю, насколько это сложно. —— Лу Ю
toSourceНе часть стандартного API, только частьFirefoxОн уникален для браузера, его не рекомендуется использовать, вы можете передать его напрямую, см.toString.
Роль: возвращает строку, представляющую исходный код массива.
грамматика:array.toSource()
const array = [1, 2, 3];
array.toSource(); // "[1, 2, 3]"
toString
Кит падает на дно моря и пятнадцать лет кормит всех существ в темном мире. - Гэри Снайдер
Функция: возвращает строку, представляющую указанный массив и его элементы.
грамматика:arr.toString()
Возвращаемое значение: строка, представляющая указанный массив и его элементы.
toStringпокрытыйObjectизtoStringМетод, который возвращает строку, содержащую каждый элемент массива, разделенный запятыми. Когда массив используется в качестве текстового значения или выполняется операция конкатенации строк, егоtoStringметод.
а такжеjoinЭффект тот же, когда параметры не передаются.Если вы хотите вручную преобразовать массив в строку, рекомендуется использоватьjoin, потому что он более гибкий.
const arr1 = [1, 2, 3];
const result = arr1.toString();
console.log(result); // "1,2,3"
toLocaleString
Движение дапэна — это не легкость пера, скорость цицзи — это не сила одной ноги. —— «Трудности божественного мужа»
грамматика:arr.toLocaleString([locales[,options]]);
параметр:
locales: Необязательно, строка или массив строк с языковыми тегами BCP 47.
options: Необязательно, одно настраиваемые свойства, для чиселNumber.prototype.toLocaleString(), на датуDate.prototype.toLocaleString().
Возвращаемое значение: строка, представляющая элемент массива.
Поскольку он существуетtoString,ТакtoLocaleStringЧтобы решить какую проблему?
КромеArrayС помощью этого APIDate,Number,ObjectЭтот API существует.
toLocaleStringа такжеtoStringОсновное отличие в том, чтоtoLocaleStringпараметр, он может преобразовать элемент в человеческий язык какой страны. Как число один миллион. Испанское представительство1.000.000, британское представительство1,000,000. То же самое верно и для дат.Например, в материковом Китае утром или днем используется 12 часов, минут и секунд, в то время как в большинстве зарубежных стран используется 24 часа, минуты и секунды.
const arr1 = [1000000, new Date()];
const resultENGB = arr1.toLocaleString("en-GB");
const resultESES = arr1.toLocaleString("es-ES");
const resultAREG = arr1.toLocaleString("ar-EG");
const resultZHCN = arr1.toLocaleString("zh-CN");
console.log(resultENGB); // "1,000,000,29/12/2019, 23:40:39"
console.log(resultESES); // "1.000.000,29/12/2019 23:40:39"
console.log(resultAREG); // ١٬٠٠٠٬٠٠٠,٢٩/١٢/٢٠١٩ ١١:٤١:٣١ م
console.log(resultZHCN); // "1,000,000,2019/12/29 下午11:40:39"
Из вышеприведенного примера можно сделать вывод, чтоtoLocaleStringОсновная цель существования — гарантировать, что браузеры пользователей в разных странах соответствуют их привычкам. Поскольку китайцы вообще не понимают арабских чисел и дат, арабам также нелегко понять китайские даты.
Второй параметр очень мощный.Сценарий приложения, как правило, для отображения валюты, и он может настроить преобразованный стиль.
const arr1 = [1000000, new Date()];
const resultGBP = arr1.toLocaleString("en-GB", {
style: "currency",
currency: "GBP",
});
const resultCNY = arr1.toLocaleString("zh-CN", {
style: "currency",
currency: "CNY",
});
console.log(resultGBP); // "£1,000,000.00,29/12/2019, 23:51:18"
console.log(resultCNY); // "¥1,000,000.00,2019/12/29 下午11:51:18"
Видно, что после установки кода банкноты номер можно преобразовать в стиль банкноты. Следует отметить, что код для юанейCNY, вместоRMB. Ну, шучу.
На самом деле вызов массиваtoLocaleStringавтоматически вызывается для каждого элементаtoLocaleString. Но, как упоминалось ранее, этот API есть только у массивов, дат, чисел и объектов, что делать, если другие типы не имеют этого API? передачаtoStringповторять
indexOf
Некоторые птицы не предназначены для содержания в клетке, и каждое их перышко сияет свободой. --"Побег из Шоушенка"
Роль: возвращает первый индекс данного элемента в массиве, и если он не существует, -1 возвращается.
грамматика:arr.indexOf(searchElement[, fromIndex])
параметр:
searchElement: Элемент для поиска.
fromIndex: Необязательно, с чего начать поиск. Если значение индекса больше или равно длине массива, это означает, что массив не будет искаться и вернет -1. Если значение индекса, предоставленное в аргументе, является отрицательным значением, оно используется как смещение в конце массива, т. е. -1 для поиска от последнего элемента, -2 для поиска от предпоследнего элемента и скоро. Примечание. Если значение индекса, указанное в параметре, является отрицательным, порядок поиска не изменяется, и порядок поиска по-прежнему остается спереди назад. Если значение индекса смещения по-прежнему меньше 0, будет запрошен весь массив. Его значение по умолчанию равно 0.
Во время ECMAScript5,indexOfвсе еще делаю один иincludesАналогичная вещь, упомянутая ранее, черезindexOfПолучите результат -1, чтобы определить, существует ли элемент в массиве. Позже, ради единой ответственности,includes. такindexOfОсновная цель в настоящее время — получить первый индекс в массиве, который соответствует параметру.
const arr1 = [1, 2, 3];
const result = arr1.indexOf(3);
console.log(result); // 2
const result2 = arr1.indexOf(21);
console.log(result2); // -1
indexOfПри сопоставлении элементов могут нормально сопоставляться только элементы примитивных типов. Как и ссылочные типы, вы должны использовать ссылки для сопоставления.
const arr1 = [];
const arr2 = [0, [], arr1];
console.log(arr2.indexOf([])); // -1
console.log(arr2.indexOf(arr1)); // 2
indexOfа такжеlastIndexOfНа самом деле это параindexOfдолжен называтьсяfirstIndexOf.
lastIndexOf
Направление важнее скорости. - Бай Янсун
Функция: возвращает индекс последнего указанного элемента в массиве или -1, если он не существует. Поиск вперед с конца массива, начиная сfromIndexначать с.
параметр:
searchElement: искомый элемент.
fromIndex: Необязательно, запустите обратный поиск из этого места. По умолчанию длина массива минус 1 (arr.length - 1), т. е. просматривается весь массив. Если значение больше или равно длине массива, поиск выполняется во всем массиве. Если отрицательный, рассматривайте его как смещение вперед от конца массива. Даже если значение отрицательное, массив все равно будет искаться в обратном направлении. Если значение отрицательное и его абсолютное значение больше длины массива, метод возвращает -1, то есть поиск в массиве производиться не будет.
Возвращаемое значение: индекс последнего вхождения этого элемента в массив или -1, если он не найден.
Почти то же самое, что и indexOf, с той лишь разницей, что сопоставление выполняется с обратной стороны.
const arr1 = [1, 2, 3, 2];
const result = arr1.lastIndexOf(2);
console.log(result); // 3
const result2 = arr1.indexOf(2);
console.log(result2); // 1
flat
Даже если мы живем в канаве, мы должны смотреть на звезды. —— Рецензия на фильм «Юность подростком»
flatЭто недавно добавленный API в 2019 году. Поскольку требование «сглаживания многомерных массивов» существовало всегда, но спрос не очень высок, чиновник не уделял ему особого внимания, и этот API не появился до тех пор, пока сейчас.
На самом деле, в раннем JavaScript, до того, как этот API не был открыт в 2019 году, мы все еще использовали наш собственный плоский API для реализации этой функции.Подробности см. в следующем содержании для конкретной реализации кода.
flatРоль очень проста, просто сгладьте массив. Насколько она плоская, решать вам.
Например, такой массив:
let arr = [1, 2, [3, 4, [5, 6, [7, 8, 9]]]];
Разложите один слой.
let result = arr.flat(1);
console.log(result);// [1, 2, 3, 4, [5, 6, [7, 8, 9]]]
Раскладываем два слоя.
let result = arr.flat(2);
console.log(result);// [1, 2, 3, 4, 5, 6, [7, 8, 9]]
Если вы не знаете, что это многомерный массив, и хотите распределить их все, передайтеInfinityВот и все.
let result = arr.flat(Infinity);
console.log(result);// [1, 2, 3, 4, 5, 6, 7, 8, 9]
Если вы позвоните напрямуюflat()Без передачи каких-либо параметров, как вы думаете, каким должен быть эффект? Это все разложено?
Тогда вы догадались неправильно.
Если никакие параметры не переданы, эффект и проход 1 совпадают.
flatMap
Никакой интеллект не остановит пустоту глупости и бездарности - "Рик и Морти"
flatMapа такжеflatродились вместе. можешь попробоватьECMAScriptУгадайте, что он делает в волшебном соглашении об именах API.
Может быть, вы угадали это правильно.flatMapрольflatа такжеmapКомбинация этих двух API.
Если вы хотите, чтобы каждый элемент в массиве копировал себя и создавал значение в два раза больше, чтобы добавить его к следующему индексу.
Вам нужно сделать два шага, сначала используйтеmapполучить эти значения, но их возвращаемое значение становится двумерным массивом.
Второй шаг, естественно, заключается в сведении возвращаемого массива в одномерный массив.
let arr = [1, 2, 3];
const result = arr.map((item) => [item, item * 2]).flat();
console.log(result);// [1, 2, 2, 4, 3, 6]
flatMapКакова роль? Это объединение связанных API в один API.
let arr = [1, 2, 3];
const result = arr.flatMap((item) => [item, item * 2]);
console.log(result);// [1, 2, 2, 4, 3, 6]
Посмотрите, какой скучный API. Я действительно восхищаюсь командой гениев лингвистического дизайна ECMA.
Это просто незначительная тирада, пожалуйста, не обращайте на это внимания.
известный писательKevin KellyВ речи он сказал:
Что касается технологии, то вначале никто не знал, для чего лучше всего подходит новое изобретение, как фонограф Аддисона, он не знал, для чего его можно использовать. Фонограф медленно использовался в двух сценариях: один — для записи последних слов, другой — для записи церковных речей, в том числе пения. Позже фонограф в основном использовался для записи музыки и так далее.
Но есть много людей в нашей жизни, у которых есть эта идея:Миру не нужны бесполезные инновации.
Я чувствую, что в мире нет бесполезных инноваций, у всех инноваций есть свое применение. Те, кто думает, что бесполезные инновации бесполезны, вероятно, не могут дождаться долгого процесса открытия новых применений для инноваций. фактически:Существовать — значит быть разумным, а быть разумным — значит существовать.
метод итерации экземпляра
Перебрать исходный массив. Во время обхода манипулирование элементами массива не затрагивается.
forEach
Тысячи запустений, это сон; - Ю Цюйюй
Действие: Выполняет предоставленную функцию один раз для каждого элемента массива.
грамматика:arr.forEach(callback(currentValue [, index [, array]])[, thisArg]);
параметр:
callback: Функция, выполняемая для каждого элемента в массиве, функция принимает три аргумента:
-
currentValue: Текущий элемент обрабатываемого массива. -
index: необязательный, индекс текущего элемента в обрабатываемом массиве. -
arrayнеобязательный,forEach()Массив, над которым работает метод.
thisArg: необязательный, необязательный параметр. Когда функция обратного вызова выполняетсяcallbackкогда используется какthisценность .
возвращаемое значение:undefined
хотяforEachКак API с наиболее частой ежедневной разработкой, все еще есть много деталей, которые не всем хорошо известны. Заставить многих студентов использоватьforEachВремя от времени происходят неожиданные явления, что сбивает с толку.
Следующая тысяча учителей будет анализироватьforEachНа какие детали обратить внимание.
forEachОбъем исполнения определяется при первом исполнении. существуетforEachВо время выполнения искусственно изменяемые элементы массива повлияютforEachисполнение. Выше мы узнали, что есть 9 способов изменить массив.
Они добавляют классы (push, unshfit, splice), удаляют классы (pop, shift, splice), заполняют классы (copyWithin, fill) и изменяют классы порядка (reverse, sort). Помимо методов самого массива,arr[i] = x,arr.length = iа такжеdelete array[i]Эти несколько способов также изменяют массив.
Начнем с простого примера.
const array = [0, 1, 2, 3, 4, 5];
array.forEach((currentValue, index, array) => {
if (currentValue % 2 === 0) {
array.push(1);
}
console.log(currentValue);
});
console.log(array);
/*
0
1
2
3
4
5
[0, 1, 2, 3, 4, 5, 1, 1, 1]
*/
Видно, что вforEachВо время процесса данные, вновь добавленные в массив, не будут просматриваться.
Но если вforEachВ процессе изменения данныхforEachбудет считывать значение в момент его прохождения. Например, отрегулируйте приведенный выше пример.
const array = [0, 1, 2, 3, 4, 5];
array.forEach((currentValue, index, array) => {
if (currentValue % 2 === 0) {
array[index + 1]++;
}
console.log(currentValue);
});
console.log(array);
/*
0
2
3
3
4
6
[0, 2, 3, 3, 4, 6, NaN]
*/
Меры предосторожности
Поскольку API слишком много, я не буду приводить примеры по одному. Вот краткий обзорforEachПравило:
1.forEachКогда начинается исполнение, определяется количество исполнений. Как бы ни менялась длина массива, он никогда не превысит это количество исполнений. Но может быть и ниже.
2.forEachВо время выполнения длина изменяется. При росте не действует, а при уменьшении завершает (пропускает) обход по достижении максимальной длины массива.
3.forEachВ процессе выполнения элементы меняются. Будет считывать значение в момент обхода элемента.
4.forEachне может быть похожеmap,filterсвязан, потому что его возвращаемое значение равноundefined, а не массив.
5. Нет другого способа прервать или выскочить, кроме как выдать исключение.forEach()цикл. Если вам нужно прервать или выйти из цикла,forEach()Методы — это не инструменты, которые следует использовать. Самый простой способ - использоватьfor,илиevery,someи другие элементы.
forEachа такжеfor
проблемы с производительностью
В более ранних браузерахforEachпроизводительность была не так хороша, какforпредставление. Так что это приводит к неправильному взгляду на всех, даже сейчас люди все еще думают, чтоforEachпроизводительность не так хороша, какfor, на самом деле это не так, благодаря оптимизации двигателя V8. Теперь в более новых браузерах или nodejs,forEachа такжеforпроизводительность сравнима, наверноеforНебольшое преимущество в производительности будет, но разрыв минимальный.
С этой целью г-н Цянь также провел эксперимент: в Chrome 79 я провел сравнение производительности массива длиной 1 миллион 5 раз:
let array = Array.from({ length: 1000000 }, (v, i) => {
return i;
});
// for
console.time("log");
for (let i = 0; i < array.length; i++) {}
console.timeEnd("log");
// log: 17.89697265625ms
// log: 12.362060546875ms
// log: 18.535888671875ms
// log: 13.59326171875ms
// log: 13.08984375ms
// forEach
console.time("log");
array.forEach(function(val, i) {});
console.timeEnd("log");
// log: 16.1630859375ms
// log: 19.702392578125ms
// log: 18.179931640625ms
// log: 19.887939453125ms
// log: 20.77197265625ms
Видно, что разрыв в производительности очень мал, даже иногдаforEachпроизводительность превзойдетfor.
Сложность
forЭто типичный продукт императивного программирования. а такжеforEachКак и другие итерационные методы, это функциональное программирование.forЕдинственным преимуществом является гибкость,breakа такжеcontinueвыпрыгнуть в любой момент. ** Но самое большое преимущество — это также и самый большой недостаток. ** Мощные функции приводят к сложному коду, который трудно читать. Например следующий код.
for (var i = 0, len = grid.length, j = len - 1, p1, p2, sum; i < len; j = i++) {
p1 = grid[i];
p2 = grid[j];
sum += p1 + p2;
}
а такжеforEachЭтого не происходит, потому что он блокируетforусловия конфигурации.
В конце концов, предложение, данное Учителем Цянем, состоит в том, что его следует использовать первым в 98% случаев.forEachИли другие итерационные методы, оставшиеся 2% должны быть в том случае, когда вам важна эта небольшая производительность, тогда вам нужно взвесить ее самостоятельно.
entries
Соответствие внутри и снаружи, слова и дела совпадают. —— Хан Фэй
Эффект: вернуть новыйArray IteratorОбъект, содержащий пары ключ/значение для каждого индекса в массиве.
грамматика:arr.entries()
Возвращаемое значение: итератор (interator) объект.
итератор итератор
Статья здесь, впервые появляетсяinteratorэто существительное. Учитель Цянь считает, что многие ученики знают это понятие, но многие ученики могут его не знать. Здесь необходимо уточнитьIteratorчто. для лучшего понимания массивов.
На самом деле, чтобы сказатьIteratorЯ могу написать статью, но тысяча преподавателей пытаются контролировать. Кратко положил эту концепцию себя ясно на линии.
этоIterableна объекте[Symbol.iterator]Атрибуты. Точнее говоря, Array также принадлежитiterable.
До ECMAScript6 объекты в JavaScript не имели возможности различать, какие объекты можно повторять, а какие нет. Мы всегда говорим, что массивы можно повторять, но мы не можем сказать, что некоторые массивоподобные объекты также могут повторяться. Хотя они могут быть повторены нами с помощью некоторых средств, таких какArray.prototype.forEach.call(). Все это объекты, и все они зависят от наших привычек определять, может ли объект повторяться или нет, и нет никакой спецификации, ограничивающей его. Это очень странно. Поэтому ECMAScript6 представил итеративный протокол для решения этой проблемы.
У всех есть[Symbol.iterator]Объекты атрибутов являются все возможные объекты (Iterable). Вызывая итерируемый объект[Symbol.iterator]метод получения итератора (iterator). вызывая итератор наnextметод повторения.
let str = "hello World!";
let iterator = str[Symbol.iterator]();
let _done = false;
while (!_done) {
const { value, done } = iterator.next();
if (!done) console.log(value);
_done = done;
}
/**
"h"
"e"
"l"
"l"
"o"
" "
"W"
"o"
"r"
"l"
"d"
"!"
**/
Почему название этого объекта такое странное? не похожеlengthЭто свойство такое же. ** Имейте в виду, что все странные дизайны в JavaScript существуют не просто так. **Поскольку до ECMAScript2015 не существовало концепции итератора. Это новое добавленное понятие, и для обеспечения совместимости его нельзя произвольно добавлять в прототип объекта.iteratorТакое свойство, иначе оно вызовет непредвиденные проблемы с предыдущим кодом JavaScript. Только что представлен ECMAScript2016Symbolконцепция. использоватьSymbolЭто может очень хорошо решить проблему конфликта атрибутов.
мы можем использоватьSymbol.iteratorсвойства для создания итерируемого объекта.
class Rand {
[Symbol.iterator]() {
let count = 0;
return {
next: () => ({
value: count++,
done: count > 5,
}),
};
}
}
var rand = new Rand();
var iterator = rand[Symbol.iterator]();
iterator.next(); // {value: 0, done: false}
iterator.next(); // {value: 1, done: false}
// ..
iterator.next(); // {value: 5, done: false}
iterator.next(); // {value: undefined, done: true}
Хотя приведенный выше код выглядит красиво, синтаксис на самом деле очень прост.Symbol.iteratorметод возвращаетnextобъект метода. а такжеnextКаждый раз, когда метод вызывается, он возвращаетvalueа такжеdoneСвойства объекта, это так просто.
valueпредставляет значение текущей итерации,doneУказывает, завершена ли итерация.
Примечание: итерируемые объекты (iterable) и объекты итератора (iterator) не одно и то же. Единственная связь заключается в том, что итерируемый объект будет содержатьSymbol.iteratorсвойство, указывающее на объект итератора.
ECMAScript6 также добавил новый синтаксис, который китайцы назвали оператором расширения (Spread syntax). Итерируемые объекты могут использовать этот оператор для расширения итерируемого объекта.
let str = "hello World!";
let iterator = str[Symbol.iterator]();
let _done = false;
console.log(...str);
/*
"h"
"e"
"l"
"l"
"o"
" "
"W"
"o"
"r"
"l"
"d"
"!"
*/
Новый в Ecmascript6.for ofГрамматика также основана наiteratorизvalueа такжеdoneездить на велосипеде.
Студенты, которые немного знакомы со структурой данных, обнаружат, что это всего лишь односвязный список? не говори,iteratorЭто односвязный список.
Разобравшись с концепцией итератора, вернемся кentriesПродолжите исследование выше.
var arr = [1, 2, 3];
var iterator = arr.entries();
iterator.next();
/*
{value: Array(2), done: false}
value: (2) [0, 1]
done: false
*/
iterator.next();
/*
{value: Array(2), done: false}
value: (2) [1, 2]
done: false
__proto__: Object
*/
entriesПреобразует массив в итератор. Каждое повторяющееся значение в этом итераторе представляет собой массив,[下标, 值]форма. Какая от этого польза? На самом деле, Учитель Цянь какое-то время не может придумать никакого применения, но когда вам понадобится его использовать, вы, естественно, узнаете, каков его сценарий применения. (Если вы помните, был такой API.)
every
Мирские дела часто создаются заветами, но побеждаются расточительством. —— Лу Ю
Роль: проверить, могут ли все элементы в массиве пройти тест указанной функции. Он возвращает логическое значение.
грамматика:arr.every(callback[, thisArg])
параметр:
callback: Функция, используемая для проверки каждого элемента, может принимать три параметра:
-
element: Текущее значение для тестирования. -
index: необязательный, индекс текущего значения для использования в тесте. -
array: опционально, звонитеeveryтекущий массив .
thisArg:воплощать в жизньcallbackиспользуется, когдаthisстоимость.
Возвращаемое значение: если каждый возврат функции обратного вызова является истинным значением, вернитеtrue, иначе возвратfalse.
everyа такжеsomeочень похоже, на самом делеeveryОчень похоже на более ранние итерации или, точнее, более ранние итерации.everyа такжеforEachРазница имеет два балла, первый балл,everyвыполнение останавливает обход, если условие не выполняется. Второй момент,everyЕсть возвращаемое значение.
const arr = [0, 1, 2, 30, 4, 5];
const result = arr.every(function(item, index) {
console.log(index);
/*
0
1
2
3
*/
return item < 10;
});
console.log(result); // false
some
Мастерство в усердии, расточительство в игре; успех в мышлении, за которым следует разрушение. - Хан Ю
Функция: проверьте, проходит ли хотя бы один элемент в массиве предоставленный функциональный тест. Он возвращает значение логического типа.
грамматика:arr.some(callback(element[, index[, array]])[, thisArg])
параметр:
callback: Функция для проверки каждого элемента принимает три аргумента:
-
elementЭлемент массива, который обрабатывается.
-
indexнеобязательныйЗначение индекса обрабатываемого элемента в массиве.
-
arrayнеобязательныйsome()Массив для вызова.
thisArg: необязательно, выполнитьcallbackиспользуется, когдаthisстоимость.
Возвращаемое значение: хотя бы один элемент в массиве проходит проверку функции обратного вызова и возвращаетtrue; все элементы не проходят проверку функции обратного вызова и возвращают false.
someа такжеeveryпохоже, разница естьsomeОбход остановится, когда встретится первый элемент, соответствующий условию. Так что здесь нечего сказать. ПучокeveryПолучите пример здесь, чтобы увидеть разницу.
const arr = [0, 1, 2, 30, 4, 5];
const result = arr.some(function(item, index) {
console.log(index);
// 0
// 1
return item < 10;
});
console.log(result); // true
filter
Рыбак рыбака видит издалека. ——《易经》
Что он делает: создает новый массив, содержащий все элементы теста, реализованного предоставленной функцией.
грамматика:var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
параметр:callback: функция для проверки каждого элемента массива. вернутьtrueУказывает, что элемент проходит проверку, сохранить элемент,falseне сохраняется. Он принимает следующие три параметра:
-
element: Элемент, который в настоящее время обрабатывается в массиве. -
index: необязательный, индекс обрабатываемого элемента в массиве. -
array: необязательный, называетсяfilterсам массив.
thisArg: необязательно, выполнитьcallbackкогда, дляthisценность .
Возвращаемое значение: новый массив элементов, прошедших тест, или пустой массив, если ни один из элементов массива не прошел тест.
можно понять одним предложениемfilter,Возьмите то, что мы хотим.
const arr = [0, 1, 2, 3, 4, 5];
const result = arr.filter(function(item, index) {
return item % 2 === 0;
});
console.log(result); // [0, 2, 4]
filterа такжеmapвпервые был добавлен в ES6api. В отсутствиеfilterчас,forEachТакого же можно добитьсяfilterФункция.
const arr = [0, 1, 2, 3, 4, 5];
let result = [];
arr.forEach(function(item, index) {
if (item % 2 === 0) {
result.push(item);
}
});
console.log(result); // true
find
Мужество ведет в рай, трусость ведет в ад. - Сенека
Функция: возвращает значение первого элемента в массиве, который удовлетворяет предоставленной тестовой функции. в противном случае вернутьсяundefined.
грамматика:arr.find(callback[, thisArg])
параметр:
callback: Функция, выполняемая для каждого элемента массива, принимает 3 аргумента:
-
element: Текущий пройденный элемент. -
index: Необязательный, текущий индекс для обхода. -
array: необязательный: сам массив.
thisArg: необязательный, используется при выполнении обратного вызоваthisОбъект.
Возвращаемое значение: значение первого элемента в массиве, которое удовлетворяет предоставленной тестовой функции, в противном случае возвращаетсяundefined.
const arr = [0, 1, 20, 30, 40];
const result = arr.find((item) => item > 10);
console.log(result);// 20
findIndex
Если я получу его, мне повезет, а если нет, то это моя жизнь, вот и все. - Сюй Жимо
Функция: возвращает первый элемент в массиве, который удовлетворяет предоставленной тестовой функции.показатель. В противном случае вернуть -1.
грамматика:arr.findIndex(callback[, thisArg])
параметр:
callback: для каждого элемента в массиве будет выполняться функция обратного вызова, и во время выполнения автоматически передаются следующие три параметра:
-
element: Текущий элемент. -
index: Индекс текущего элемента. -
array:передачаfindIndexмассив .
thisArg: необязательный. воплощать в жизньcallbackтак какthisстоимость объекта.
Возвращаемое значение: первый элемент массива, предоставленного тестовой функцией.показатель. В противном случае вернуть -1.
findIndexВозвращаемый результатfindВозвращает индекс элемента.
const arr = [0, 1, 20, 30, 40];
const result = arr.findIndex((item) => item > 10);
console.log(result);// 2
keys
Высоко оценивая мудрый, знающий тех. Те, кто побеждает других, сильны, а те, кто побеждает себя, сильнее. - Лао-цзы
Функция: возвращает массив, содержащий каждый ключ индекса в массиве.Array Iteratorобъект.
грамматика:arr.keys()
Возвращаемое значение: новый объект итератора Array.
let arr = ['a', 'b', 'c'];
const result = arr.keys();
for(let key of result){
console.log(key);
}
/*
0
1
2
*/
Функция состоит в том, чтобы преобразовать массив в итератор, который хранит все индексы массива.
keysа такжеObject.keysразница в том,keysне будет игнорироватьemptyэлемент.
let arr = ['a', ,'b', , 'c', ,];
const result = arr.keys();
for(let key of result){
console.log(key);
}
/*
0
1
2
3
4
5
*/
map
Если есть, измените, если нет, добавьте поощрения. - "Аналекты"
Что он делает: создает новый массив, результат которого является результатом вызова предоставленной функции для каждого элемента в массиве.
грамматика:
var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])
параметр:
callback: функция, создающая новый элемент массива, принимает три аргумента:
-
currentValue:callbackТекущий элемент обрабатываемого массива. -
index: необязательный,callbackИндекс текущего элемента в обрабатываемом массиве. -
array: необязательный,mapМассив вызовов методов.
thisArg: необязательно, выполнитьcallbackзначение времени функции используется какthis.
Возвращаемое значение: Результат функции обратного вызова формирует каждый элемент нового массива.
mapЭто самая старая партия API в ECMAScript2015, и ее основная функция — сопоставление массива. его функция использованияforEachТого же можно добиться.
Например, удвоение всех элементов массива.
let arr = [1, 2, 3, 4, 5, 6, 7];
const result = arr.map(function(item) {
return item * 2;
});
console.log(result);// [2, 4, 6, 8, 10, 12, 14]
forEachТо же самое может быть достигнуто, но более чемmapЕще немного неприятностей.
let arr = [1, 2, 3, 4, 5, 6, 7];
const result = [];
arr.forEach(function(item) {
result.push(item * 2);
});
console.log(result);// [2, 4, 6, 8, 10, 12, 14]
Поскольку и то, и другое может быть достигнуто, хотяmapБолее лаконично. Итак, когда его следует использоватьmapШерстяная ткань?
1. Необходимость возврата нового массива.
2. Нужно ли вам получать возвращаемое значение из функции обратного вызова.
Можно использовать любое условиеmap, иначе используйтеforEachилиfor...of.
Чаще всего используется для извлечения некоторого значения из массива объектов.
let arr = [
{ name: "dog", age: 11 },
{ name: "cat", age: 4 },
{ name: "小明", age: 15 },
];
const result = arr.map(function(item) {return item.age});
console.log(result); // [11, 4, 15]
когда вы не знаете, следует ли вам использоватьmapНе беспокойтесь об этом, потому чтоmapСамое большое значение состоит в том, чтобы упростить некоторый код.
reduce
Жизнь человека коротка, но слишком длинна, если прожить ее подло. - Шекспир
Действие: Выполняет предоставленный вами массив для каждого элемента в массиве.reducerФункция (выполняемая в порядке возрастания), которая объединяет свои результаты в одно возвращаемое значение.
грамматика:arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
параметр:
callback: выполняет каждое значение в массиве (если не указаноinitialValue则第一个值除外) функция с четырьмя параметрами:
-
accumulator: возвращаемое значение обратного вызова накопления аккумулятора; это накопленное значение, возвращенное при последнем вызове обратного вызова, илиinitialValue(Смотри ниже). -
currentValue: элемент обрабатываемого массива. -
index: необязательный, индекс текущего элемента в обрабатываемом массиве. если предусмотреноinitialValue, то начальный номер индекса равен 0, иначе он начинается с индекса 1. -
array: опционально, звонитеreduce()массив .
initialValue: необязательно, как первый вызовcallbackЗначение первого параметра функции. Если начальное значение не указано, будет использован первый элемент массива. Вызов сокращения для пустого массива без начального значения вызовет ошибку.
Возвращаемое значение: совокупный результат обработки функции.
let arr = [1, 2, 3, 4, 5, 6];
const result = arr.reduce(function(acc, val) {
return acc + val;
});
console.log(result);// 21
а такжеmap,filterПо сравнению с другими API,reduceКажется немного другим. В чем разница?
reduceБуквально означает «уменьшать», на самом деле правильнее называть это комбинацией.
Например, в фитнесе учитываются белки, жиры и углеводы.
Это таблица питания пищи.
const nutritionFacts = {
"🥚": {
carbohydrate: 3,// 碳水化合物
protein: 13,// 蛋白质
fat: 9,// 脂肪
calories: 144// 热量
},
"🍏": {
carbohydrate: 12,
protein: 0,
fat: 0,
calories: 52
},
"🍌": {
carbohydrate: 21,
protein: 1,
fat: 0,
calories: 91
},
"🍞": {
carbohydrate: 58,
protein: 8,
fat: 5,
calories: 312
},
"🥦": {
carbohydrate: 3,
protein: 4,
fat: 1,
calories: 33
},
"🥩": {
carbohydrate: 2,
protein: 20,
fat: 4,
calories: 125
}
};
Ниже мы можем пройтиreduceдля инкапсуляции функции, которая вычисляет тепло.
const calculation = (foods) => {
return foods.reduce((nutrition, food) => {
return {
carbohydrate:
nutritionFacts[nutrition].carbohydrate +
nutritionFacts[food].carbohydrate,
protein: nutritionFacts[nutrition].protein + nutritionFacts[food].protein,
fat: nutritionFacts[nutrition].fat + nutritionFacts[food].fat,
calories:
nutritionFacts[nutrition].calories + nutritionFacts[food].calories
};
});
};
const result = calculation(["🥩", "🥦"]);
console.log(result);
/*
{
calories: 158,
carbohydrate: 5,
fat: 5,
protein: 24
}
*/
Вы можете попробовать немного, тогда из приведенного выше кода можно найти ОШИБКУ. Если нет, пожалуйста, продолжайте попытки.
Ошибка в том, что если вы съедите только кусок говядины, он вернет вам говядину в целости и сохранности. (Это неправда, правильный ответ должен быть 💩)
const result = calculation(["🥩"]);
console.log(result);// "🥩"
Итак, как это исправить?
Первое, что нужно сделать, это определить причину, в чем причина этого явления? вы, возможно, обнаружили, что еслиreduceзвонящегоlengthКогда он равен 1, он не будет звонитьcallbackлогика, но возвращает элемент напрямую.
Тогда по этой идее метод преобразования вообще основан на входящих параметрахfoodsизlengthдать возвращаемое значение, еслиlengthЕсли он равен 1, он напрямую вернет соответствующий состав питательных веществ. Можно написать следующий код:
if (foods.length === 1) {
const { carbohydrate, protein, fat, calories } = nutritionFacts[foods[0]];
return {
carbohydrate,
protein,
fat,
calories
};
} else if (foods.length < 1) {
// 原来的逻辑
}
Но это явно выглядит неуклюже. Есть ли более мудрый подход? Конечно есть, не забывайтеreduceЕсть еще второй параметр. Если второй параметр не передан, в качестве начального состояния будет использоваться первый параметр. В этом случае первое значение будет пропущено. Но если есть второй параметр, первое значение не будет пропущено. Таким образом, мы можем решить эту проблему более элегантно со вторым параметром.
nutritionFacts["💧"] = {carbohydrate: 0, protein: 0, fat: 0, calories: 0};// 添加 💧 默认所有营养都为0
const calculation = (foods) => {
return foods.reduce((nutrition, food) => {
return {
carbohydrate:
nutritionFacts[nutrition].carbohydrate +
nutritionFacts[food].carbohydrate,
protein: nutritionFacts[nutrition].protein + nutritionFacts[food].protein,
fat: nutritionFacts[nutrition].fat + nutritionFacts[food].fat,
calories:
nutritionFacts[nutrition].calories + nutritionFacts[food].calories
};
}, "💧");
};
Умные одноклассники нашли уравнение.
["🥩", "🥦"].reduce(reducer, initialState);
[initialState, "🥩", "🥦"].reduce(reducer);
Вышеупомянутые два использования имеют тот же самый эффект.
Если вы использовали Redux или Rxjs, вы должны увидеть что-то знакомое из приведенного выше кода.reducerа такжеinitialState.
Да, все они используют одни и те же идеи и принципы.
Вы можете думать об этом так, в ReduxreduceЭто не делается автоматически синхронно, а активируется вручную асинхронно.reducerпервый параметрcurrentStateявляется текущим базовым состоянием. каждый раз разныеactionсработает один разreduceвызов. пройти черезreducerвторой параметрcurrentValueа такжеreducerлогика для измененияcurrentState,currentValueСоответственно в ReduxActionпереданные параметрыtypeа такжеpayload.
Вы можете быть немного сбиты с толку, но ничего страшного, вы поймете рано или поздно.
forто же самое может быть достигнутоreduce. Как считать углеводы.
let foods = ["🥩", "🥦"];
let result = {};
for(let i = 0; i < foods.length; i++) {
result.carbohydrate = (result.carbohydrate || 0) + nutritionFacts[foods[i]].carbohydrate;
}
console.log(result);// { carbohydrate: 5 }
Как видно из приведенного выше примера,forСравниватьreduceДобавлена еще одна переменная для хранения значения результата последнего расчета.
reduceНа самом деле такое значение есть, но благодаря преимуществам функционального программирования оно вам напрямую не видно. Может быть, ты не чувствуешь этого сейчасreduceСравниватьforКакое большое преимущество. Но когда вы сталкиваетесь с файлом кода с сотнями строк,reduceПреимущество автоматического обслуживания этой переменной для вас снова легкое.
Еще одно замечание,reduceБуквально уменьшая, на самом деле не уменьшая. Потому что первым параметром в его функции обратного вызова может быть любое значение, например массив или объект. Поскольку это массив или объект, это структура данных, которую можно бесконечно расширять. Итак, не будьreduceБуквально обманул.
let arr = [0, 1, 2, 3, 4, 5];
const result = arr.reduce((accumulator, currentValue) => {
accumulator.push(currentValue * 2);
return accumulator;
}, []);
console.log(result);// [0, 2, 4, 6, 8, 10]
Смотреть,reduceможно добиться чего-то вродеmapфункция. такой же,reduceтакже может быть достигнутоforEach,filterи другие функции.
reduceRight
Не избегайте огорчений и трудностей, вполне справитесь с трудностями, значит, преодолевайте их. - Дайсаку Икеда
Что он делает: принимает функцию как аккумулятор и сводит каждое значение массива (справа налево) к одному значению.
грамматика:arr.reduceRight(callback(accumulator, currentValue[, index[, array]])[, initialValue])
параметр:
callback: функция обратного вызова, которая работает с каждым элементом массива и принимает четыре параметра:
-
accumulator: возвращаемое значение последнего вызова функции обратного вызова илиinitialValue。 -
currentValue: элемент, который в данный момент обрабатывается. -
index: Необязательный, индекс элементов, обрабатываемых в данный момент в массиве. -
array: опционально, звонитеreduceRight()массив .
initialValue: необязательный, значение используется в качестве накопителя для первого вызова обратного вызова. Если начальное значение не указано, будет использован последний элемент массива, который будет пропущен. Вызов reduce или reduceRight для пустого массива без начального значения создаст TypeError.
Возвращаемое значение: возвращаемое значение после выполнения.
reduceRightа такжеreduceЭто близнец, за исключением того, что он повторяется сзади вперед. можно сравнитьindexOfа такжеlastIndexOf.
values
Я ни с кем не спорю и ни с кем не спорю. - Ранд
Эффект: вернуть новыйArray IteratorОбъект, содержащий значение для каждого индекса массива.
грамматика:arr.values()
Возвращаемое значение: новыйArrayИтерация по объектам.
let arr = ['a', 'b', 'c'];
const iterator = arr.values();
for(let item of iterator){
console.log(item);
}
/*
"a"
"b"
"c"
*/
Symbol.iterator
Все индивидуалисты подразумевают силу - Камю
эффект:@@iteratorсвойства иArray.prototype.values()Начальным значением свойства является тот же объект функции.
грамматика:arr[Symbol.iterator]()
Возвращаемое значение: сvaluesтакой же.
Как правило, не рекомендуется использовать этот метод, непосредственно используйтеvaluesДостаточно.
let arr = ['a', 'b', 'c'];
const iterator = arr[Symbol.iterator]();
for(let item of iterator){
console.log(item);
}
/*
"a"
"b"
"c"
*/
Методы объектов, связанные с массивом
entries
Забыть прошлое означает предательство. - Ленин
Функция: возвращает массив пар ключ-значение собственных перечисляемых свойств данного объекта, которые упорядочены и используются.for...inПеребор объекта в цикле возвращает тот же порядок (разница в том, что цикл for-in также перечисляет свойства в цепочке прототипов).
грамматика:Object.entries(obj)
параметр:obj: объект, который может возвращать пары ключ-значение своих перечисляемых свойств.
Возвращаемое значение: Массив пар ключ-значение для собственных перечисляемых свойств данного объекта.
let animals = {"dog": "🐶", "cat": "🐱", "bird": "🐦", "wolf": "🐺"};
const result = Object.entries(animals);
console.log(result);// [["dog", "🐶"], ["cat", "🐱"], ["bird", "🐦"], ["wolf", "🐺"]]
После преобразования объекта в массив порядок элементов не зависит от порядка определения объекта, но порядок такой же, какfor...inБыть последовательным.
entriesСуществует два распространенных сценария применения.
1. Пересеките объект
for(let [key, value] of Object.entries(animals)) {
console.log(`${key}:${value}`);
}
/*
"dog:🐶"
"cat:🐱"
"bird:🐦"
"wolf:🐺"
*/
или использоватьforEach, результат тот же.
Object.entries(animals).forEach(([key, value]) => console.log(`${key}: ${value}`));
/*
"dog: 🐶"
"cat: 🐱"
"bird: 🐦"
"wolf: 🐺"
*/
2. Преобразовать в карту
const map = new Map(Object.entries(animals));
console.log(map.size); // 4
console.log(map.has('dog')); // true
console.log(map.get('cat')); // "🐱"
keys
От добра к восхождению, от зла к падению. 11 «Национальный язык»
Функция: возвращает массив, состоящий из собственных перечислимых свойств данного объекта, порядка и использования имен свойств в массиве.for...inПорядок, возвращаемый при циклическом просмотре объекта, является согласованным.
грамматика:Object.keys(obj)
параметр:obj: Объект, свойства которого должны быть возвращены для перечисления самого себя.
Возвращаемое значение: массив строк, представляющих все перечисляемые свойства данного объекта.
keysЭто собрать все перечисляемые имена свойств объекта в массив.
let animals = {"dog": "🐶", "cat": "🐱", "bird": "🐦", "wolf": "🐺"};
const result = Object.keys(animals);
console.log(result);// ["dog", "cat", "bird", "wolf"]
values
Гонг Чонг только амбиции, широкая промышленность, но прилежный. 11 "Шаншу"
Роль: возвращает массив всех перечисляемых значений свойств самого данного объекта.
грамматика:Object.values(obj)
параметр:obj: Объект, перечисляемые значения свойств которого возвращаются.
Возвращаемое значение: Массив, содержащий значения всех перечисляемых свойств самого объекта.
valuesспособ работы иentriesочень похожий. Оба они автоматически игнорируют цепочку прототипов и неперечислимые свойства.
let animals = {"dog": "🐶", "cat": "🐱", "bird": "🐦", "wolf": "🐺"};
const result = Object.values(animals);
console.log(result);// ["🐶", "🐱", "🐦", "🐺"]
valuesОбъекты могут быть легко преобразованы в наборы.
let animals = {"dog": "🐶", "cat": "🐱", "bird": "🐦", "wolf": "🐺"};
const set = new Set(Object.values(animals));
console.log(set); // Set(4) {"🐶", "🐱", "🐦", "🐺"}
valuesа такжеkeysпредставляет собой пару API со схожими функциями.
fromEntries
Жизнь не может продолжаться без того, чтобы многое забыть. - Бальзак
Роль: преобразовать список пар ключ-значение в объект.
грамматика:Object.fromEntries(iterable);
параметр:iterable: повторяемый объект, напримерArray,MapИли другие объекты, реализующие итерируемый протокол.
Возвращаемое значение: новый объект со свойствами, предоставленными этой записью объекта итерации.
fromEntriesэто недавно добавленный API в 2019 году,fromEntriesдаentriesОбратная функция, предназначенная также для решенияentriesПосле использования данные сохраняются в массиве необратимо.
let animals = {"dog": "🐶", "cat": "🐱", "bird": "🐦", "wolf": "🐺"};
const animalsList = Object.entries(animals);
const animals2 = Object.fromEntries(animalsList);
console.log(animals2);
/*
{
bird: "🐦",
cat: "🐱",
dog: "🐶",
wolf: "🐺"
}
*/
fromEntriesроль не ограничиваетсяArrayПеревести вObject, он может преобразовать все итерируемые объекты в объект, напримерSetа такжеMap.
Строка в массив
split
Когда нечего делать или устаешь, мудрецы расценивают их как самосовершенствование. - Цзо Цзунтан
Роль: используйте указанную строку-разделитель для преобразованияStringОбъект разбивается на массив подстрок с указанной строкой разделения для определения позиции каждого разделения.
грамматика:str.split([separator[, limit]])
параметр:
separator: указывает строку, представляющую точку, в которой должно произойти каждое разделение.separatorЭто может быть строка или регулярное выражение. Если разделитель содержит множество символов обычного текста, необходимо найти всю строку, представляющую точку разделения. Если опущен или не указан разделитель str, возвращаемый массив содержит один элемент из состава всей строки. Если разделитель представляет собой пустую строку, то возвращается массив строк str исходного символа каждого символа.
limit: целое число, определяющее количество возвращаемых разделенных сегментов. Если указан этот параметр, метод split разбивает строку при каждом появлении указанного разделителя, но останавливается, когда запись ограничения помещается в массив. Если конец строки достигнут до того, как будет достигнуто указанное ограничение, она все равно может содержать меньше записей, чем ограничение. Оставшийся текст не возвращается в новом массиве.
Возвращаемое значение: возвращает массив исходной строки, разделенный позицией вхождения разделителя.
const str = "hello,world!";
const result = str.split(',');
console.log(result);// ["hello", "world!"]
использоватьsplitРазделите строку, чтобы получить массив, в котором каждый элемент является подстрокой исходной строки.
Если вы хотите восстановить этот массив вырезов, вы можете использоватьjoin.
const str2 = result.join(',');
console.log(str2);// "hello,world!"
Резюме: Столкнувшись с таким обширным и сложным API, что нам делать?
Во времена ECMAScript 5.0 было не так много API. Вы можете перейти к «Продвинутому программированию на JavaScript (3-е издание)», там всего несколько ключевых API.
На данный момент очень немногие люди могут полностью понять, какой API следует использовать в какой ситуации, не прибегая к документации. Вы должны знать, что многие API, представленные выше, представляют собой просто тип данных, такой как сам массив. А вы уверены, что помните и понимаете все вышеперечисленное? Я уверен, что вы мало что помните. Возможно, вы сейчас боретесь с тем, как запомнить их.
Предложение учителя таково:Не запоминайте их намеренно, это не имеет смысла.
Если вы работник, который давно имеет дело с JavaScript, или старший энтузиаст JavaScript, вы можете надлежащим образом использовать эти функции при рефакторинге старых проектов и разработке новых проектов. Но обратите внимание на поддержку Transplier. **Практика — отличное средство для углубления памяти. **Когда вы потренировались до определенного уровня, вы можете пойти к своим сверстникам, чтобы пообщаться и поделиться своим опытом друг с другом. Не оставайтесь в рамках своих собственных знаний, выходите и больше гуляйте.
Если вы не очень часто сталкиваетесь с JavaScript или если JavaScript не является вашим единственным языком, например, вы являетесь инженером с полным стеком, который одновременно освоил другие языки, такие как Java. Тогда вам не нужно запоминать все API. Потому что со стороны Java нужно помнить все больше и больше важных вещей.
Тем не менее, вы все равно должны помнить несколько ключевых и основных API.
Какие ключевые и основные? Эти API в эпоху ECMAScript5.0 и первая партия API, добавленная ECMAScript2015. Запомните их, и вы сможете решить все сценарии. Что касается API после ECMAScript2015, большинство из них предназначены для исправления некоторых исторических проблем или для реализации дизайна с единой ответственностью. Интересно, но не обязательно действительно полезно.
Волшебное оружие: инструмент для новичков и ленивых
Поскольку слишком много API-интерфейсов Array, нет серьезного изучения и понимания, плюс много практики и опыта. Трудно запомнить все API. В ответ на эту ситуацию Учитель Цянь написал эту статью. Но эта статья немного больше, чем это. Учитель Цянь также учился быть ленивым. Например, сейчас вы не помните и не понимаете все API, но вам нужно их использовать, и использовать правильно. Как это сделать? Проверять документацию каждый раз очень медленно.
Все в порядке, красивый программистSarah DrasnerИнструмент Array с открытым исходным кодомArrayExplorer. Вам просто нужно выбрать операцию массива, необходимую для получения соответствующего API.
На самом деле, г-н Цянь считал, что как главному инженеру нет необходимости осваивать Array.Конечно, если вы хотитеКак необычный инженер, г-н Цянь все же рекомендует вам освоить Array. ** Так что не рискуйте, это благословение, а не бедствие, это бедствие, которого нельзя избежать. Учитель Цянь считает, что каждый из вас, кто читает эту статью, не будет простым инженером.
Вишенка на торте: Расширения сообщества для Array
Как расширить прототип?
Благодаря гибкой системе прототипов ECMAScript каждый тип данных может добавлять новые функциональные возможности с помощью расширений прототипа.
Это сильно отличается от Java. Java расширяет массивы посредством наследования.
class MyArrayList extends ArrayList{
public void hello(){
System.out.println("hello");
}
}
И при использовании массивов после этого вы больше не можете использовать ArrayList, вместо этого используйте MyArrayList.
MyArrayList arr = new MyArrayList();
arr.add(1);
arr.add("2");
arr.hello();// hello
В дополнение к этому есть еще один способ — напрямую модифицировать JDK.
А ECMAScript намного проще. После расширения это не влияет на исходное использование.
Array.prototype.hello = function() {
console.log("hello");
}
[].hello();// hello
Конечно, ECMASCript также поддерживает наследование для расширения.
class MyArray extends Array {
hello() {
console.log("hello");
}
}
Недостаток очевиден, способ создания массива можно передатьnewКлючевое слово, буквальный подход не сработает. А согласно нашим привычкам, 99% людей любят использовать литералы.
var arr = new MyArray();
arr.hello(); // hello
var arr2 = [];
arr2.hello(); // Uncaught TypeError: [].hello is not a function
С точки зрения расширения прототипа, прототип.js является основоположником отрасли. Их примеру последовали такие фреймворки, как right.js, ext.js и undersore.js. Было долгое время, когда почти каждая библиотека расширяла возможности Array. Это все равно, что называть себя библиотекой JavaScript, не расширяя Array. Массив уже имеет свойства и методы 30. Когда вы расширяете массив, вы думаете о массиве? Конечно, никто из них об этом не думал, но ECMA думал об этом. Так что теперь нативный Array очень и очень мощный, а эти библиотеки недостаточно хороши.
Сейчас, кроме lodash.js, других однотипных библиотек почти не осталось. Но методы, которые они расширяют, действительно просто необходимы, потому что эти методы — решения, с которыми каждый сталкивается при написании бизнеса, поэтому их все же стоит изучить. Если вы чувствуете, что изучать эти вещи сейчас не очень осмысленно, значит, количества написанного вами кода все еще недостаточно, и вы будете писать более сложный бизнес, и рано или поздно столкнетесь со сценариями использования.
Расширенная реализация API
Учитель Цянь порекомендовал относительно зрелую библиотеку расширения массива,d3-array. Эта библиотека очень полная и может использоваться непосредственно в проекте.
Ниже показана реализация некоторых наиболее распространенных методов расширения.
remove
Функция: удаление элементов на основе индексов.
выполнить:
Array.prototype.remove = function(index) {
return !!this.splice(index, 0);
};
Применение:
var arr = ["a", "b", "c"];
const result = arr.remove(1);
console.log(result); // true
console.log(arr); // ['a', 'c']
removeAt
Роль: удалять элементы на основе элементов
выполнить:
Array.prototype.removeAt = function(item) {
const index = this.indexOf(item);
if (index !== -1) {
return !!this.splice(index, 1);
}
return false;
};
Применение:
var arr = ["a", "b", "c"];
const result = arr.removeAt(1);
console.log(result); // true
console.log(arr); // ['b', 'c']
shuffle
Функция: Перетасовать массив и перетасовать элементы массива.
Алгоритм перетасовки — относительно сложный API. Это очень старая задача, восходящая к алгоритму тасования Кнута в 1938 году, еще до нашего рождения.
Этапы операции перетасовки Кнута примерно следующие:
1. Запишите числа от 1 до длины-1.
2. Выбрать случайное число k от 1 до оставшихся непройденных чисел.
3. Считаем с конца, каждый раз удаляем случайно выбранное k и помещаем его в конец массива.
4. Повторяйте шаги 2-3, пока не будут пройдены все числа.
Его суть заключается в использованииMathпредоставленный объектrandomфункция.
Добиться хороших библиотек на npm уже есть,knuth-shuffle-seededа такжеknuth-shuffle.
выполнить:
Array.prototype.shuffle = function() {
for (len = this.length - 1; i > 0; i--) {
rand = Math.floor(Math.random() * i);
temp = this[rand];
this[rand] = this[i];
this[i] = temp;
}
};
Применение:
let arr = [0, 1, 2, 3, 4, 5, 6];
arr.shuffle();
console.log(arr); // [5, 4, 6, 1, 0, 2, 3]
random
Действие: Произвольно удалить элемент из массива.
выполнить:
Array.prototype.random = function() {
return this[Math.floor(Math.random() * this.length)];
};
Применение:
let arr = [0, 1, 2, 3, 4, 5, 6];
const result = arr.random();
console.log(result);
flatten
Функция: сгладить массив и вернуть одномерный массив.
выполнить:
Array.prototype.flatten = function() {
let result = [];
this.forEach(function(item) {
if (Array.isArray(item)) {
result = result.concat(item.flatten());
} else {
result.push(item);
}
});
return result;
};
Применение:
let arr = [0, [1, 2], 3, [[[4], 5], 6]];
const result = arr.flatten();
console.log(result); // [0, 1, 2, 3, 4, 5, 6]
После ECMAScript2019 собственный массивflatAPI, этот сторонний API больше не нужен. Но его все еще можно использовать в более высоких средах.
unique
Функция: дедуплицировать массив и вернуть массив без повторяющихся элементов.
До ECMAScript6,uniqueРеализация относительно громоздкая, но после ECMAScript6 появились новые структуры данныхSet,uniqueреализация очень проста.
использоватьSetвыполнить:
Array.prototype.unique = function() {
let set = new Set(this);
return [...set];
};
Реализация ECMAScript5:
Array.prototype.unique = function() {
var result = [];
loop: for (let i = 0; i < this.length; i++) {
for (let j = i + 1; j < this.length; j++) {
if (this[i] === this[j]) {
continue loop;
}
}
result.push(this[i]);
}
return result;
};
Применение:
let arr = [0, 1, 1, 1, 2, 3, 3];
const result = arr.unique();
console.log(result); // [0, 1, 2, 3]
compact
Функция: удалить null и undefined из массива и вернуть новый массив.
выполнить:
Array.prototype.compact = function() {
return this.filter(function(item) {
return item != null;
});
};
Применение:
let arr = [0, null, 1, , undefined, 2];
const result = arr.compact();
console.log(result); // [0, 1, 2]
pluck
Функция: получить свойство каждого объекта в массиве и сформировать возвращаемый массив.
выполнить:
Array.prototype.pluck = function(propertyName) {
let result = [];
this.forEach(function(item) {
if (propertyName in item) {
result.push(item[propertyName]);
}
});
return result;
};
Применение:
let arr = [
{ name: "dog", age: 11 },
{ name: "cat", age: 4 },
{ name: "小明", age: 15 },
];
const result = arr.pluck("age");
console.log(result); // [11, 4, 15]
groupBy
Роль: группировать по заданным условиям и возвращать объекты.
выполнить:
Array.prototype.groupBy = function(key) {
return this.reduce((acc, i) => {
(acc[i[key]] = acc[i[key]] || []).push(i);
return acc;
}, {});
}
использовать:
let arr = [
{
name: "金庸",
profession: "作家"
},
{
name: "李小龙",
profession: "武术家"
},
{
name: "古龙",
profession: "作家"
}
];
const result = arr.groupBy("profession");
console.log(result);
/*
{
作家: [
{
name: "金庸",
profession: "作家"
},
{
name: "古龙",
profession: "作家"
}
],
武术家: [
{
name: "李小龙",
profession: "武术家"
}
]
}
*/
Этот API вдохновлен SQLGROUP BYработать.
union
Функция: возьмите объединение двух массивов.
воплощение идей иuniqueОчень похоже, два массива соединяются вместе, а затем дедуплицируются.
выполнить:
Array.prototype.union = function(arr) {
let set = new Set(this.concat(arr));
return [...set];
};
Применение:
const result = [1, 2, 3, 4, 5].union([2, 3, 4, 5, 6]);
console.log(result);// [1, 2, 3, 4, 5, 6]
intersect
Функция: взять пересечение двух массивов.
выполнить:
Array.prototype.intersect = function(arr) {
return this.filter(function(item) {
return ~arr.indexOf(item);
});
};
Применение:
const result = [1, 2, 3, 4, 5].intersect([2, 3, 4, 5, 6]);
console.log(result);// [2, 3, 4, 5]
diff
Функция: Найдите разницу между двумя массивами.
Array.prototype.diff = function(arr) {
let result = [];
for(let i = 0;i < this.length; i++) {
if(!arr.includes(this[i])) {
result.push(this[i]);
}
}
return result;
}
Применение:
let arr = ['🐇', '🐘', '🐿️', '🐑'];
let arr2 = ['🐇', '🐑', '🐒', '🐄'];
const result = arr.diff(arr2);
console.log(result);// ["🐘", "🐿️"]
min
Функция: взять минимальное значение в массиве, используется только для числовых массивов.
Идея состоит в том, чтобы использоватьMath.minа такжеapplyСочетание этих двух функций.
Array.prototype.min = function() {
return Math.min.apply(0, this);
}
Применение:
const result = [1, 2, 3, 4, 5].min();
console.log(result);// 1
max
Функция: взять максимальное значение в массиве, используется только для числовых массивов.
maxИдея реализации аналогичнаmin.
Array.prototype.max = function() {
return Math.max.apply(0, this);
}
Применение:
const result = [1, 2, 3, 4, 5].max();
console.log(result);// 5
chunk
Задача: разделить большой массив на N меньших массивов.
Array.prototype.chunk = function(size) {
let chunked = [];
let arr = this.slice();
while(arr.length) {
chunked.push(arr.splice(0, size));
}
return chunked;
}
Применение:
const arr = [1, 2, 3, 4, 5, 6, 7];
const result1 = arr.chunk(2);
console.log(result1);// [[1, 2], [3, 4], [5, 6], [7]]
const result2 = arr.chunk(3);
console.log(result2);// [[1, 2, 3], [4, 5, 6], [7]]
const result3 = arr.chunk(4);
console.log(result3);// [[1, 2, 3, 4], [5, 6, 7]]
Суммировать
Как не загрязнить цепочку прототипов?
Все приведенные выше примеры реализованы путем расширения цепочки прототипов. Если вы не хотите изменять цепочку прототипов, вы также можете реализовать эти функции другими способами, например, записав их все в виде функций или записав их как класс.
Пример написания класса уже упоминался в начале этого раздела. Здесь я в основном говорю о том, как переписать его в функцию, что на самом деле очень просто.removeВозьмите пример.
Как реализована цепочка прототипов:
Array.prototype.remove = function(index) {
return !!this.splice(index, 0);
};
Способ переписать его как функцию:
function remove(arr, index) {
return !!arr.splice(index, 0);
};
Применение:
remove([1, 2, 3, 4], 1);
Просто добавьте параметр массива в начало исходного списка параметров функции,thisИзменить входящие параметры на входящие параметры очень просто, преимущество этого в том, что исходные привычки использования массива не изменятся.
Стремление к элегантному минимализму
Есть много людей, которые одержимы кодом. Они тщательно изучают код и предпочитают более элегантную реализацию. Лямбда-выражение (лямбда) — это средство предельного упрощения кода.
такие как использованиеlambdaправильноchunkРеализация упрощается.
Array.prototype.remove = index => !!arr.splice(index, 0);
Это намного проще. Но это не кажется очевидным, потому что исходная реализация очень короткая. Итак, давайте посмотрим на другой пример.
использоватьMath.ceilправильноchunkСделайте макияж.
const chunk = (arr, n) => [...new Array(Math.ceil(arr.length / n))].map((x, i) => arr.slice(i * n, (i + 1) * n ));
Можете ли вы увидеть некоторые сравнения сейчас? N строк кода преобразуются в 1 строку.
У всех есть две стороны, хотя она выглядит более лаконичкой, но для понимания этой линии кода стоимость выше оригинального способа написания.
Программирование - это искусство, и так как это искусство, нет абсолютных плюсов и минусов. Потому что у каждого есть другое понимание работы.
Идеи для расширения API
На самом деле, если вы достаточно внимательны, вы можете обнаружить, что все API-интерфейсы расширений более или менее зависят от исходного API или других API. Объедините операции, которые изначально требовали двух или более шагов, в простой в использовании API. Если вы играли в League of Legends, вы должны знать, что есть герой по имени Ривен, и у нее есть комбо под названием Lightspeed QA. Это комбо может нанести взрывной урон за очень короткий промежуток времени, но операция очень громоздкая. Требуется "щелкнуть правой кнопкой мыши врага, чтобы выполнить обычную атаку-клавиша Q на клавиатуре, чтобы активировать навык-щелкнуть правой кнопкой мыши пол, чтобы отменить Q навык жесткий прямой», а затем повторите эту операцию 3 раза. Пожилым людям не угнаться за скоростью рук, и такое комбо сложно сделать без ошибок. Но люди среднего возраста часто умнее.Они используют функцию макроса мыши, чтобы заранее соединить операции комбо и ввести их в мышь.Когда им нужно ее использовать, им нужно только нажать кнопку макроса, чтобы легко реализовать этот набор утомительных операций. Этот принцип очень похож на API расширения. Следуя этому направлению мысли, вы можете придумать и создать больше служебных API.
Дополнительное чтение: обработка на уровне двигателя V8
В четырех вопросах души мы знаем, что диапазон памяти массива фиксирован, но JavaScript это не волнует.
На уровне языка, поскольку JavaScript его игнорирует, как это обрабатывается на уровне движка?
Внутри элементы массива называются V8elements. В целях оптимизации производительности V8 подвергается специальной обработке. Более того, точнее различается тип. Например, элемент типа «Число» на уровне языка, JavaScript только одинtypeofоператор, чтобы узнать, является ли переменная числом, но не является ли она целым числом, числом с плавающей запятой или двойным числом. Внутри V8, если все элементы массива имеют целочисленный тип, то тип массива помечен какPACKED_SMI_ELEMENTS. Если есть только целые типы и типы элементов с плавающей запятой, то тип массиваPACKED_DOUBLE_ELEMENTS. Кроме того, массив содержит другие элементы, помеченные какPACKED_ELEMENTS. И эти типы массивов не являются статическими, а изменяются в любое время во время выполнения. Но тип массива можно изменить только с определенного типа на общий тип. это изначальноPACKED_SMI_ELEMENTS, который может быть переведен только вPACKED_DOUBLE_ELEMENTSилиPACKED_ELEMENTS. а такжеPACKED_DOUBLE_ELEMENTSтолько переход кPACKED_ELEMENTS. Что касается начальногоPACKED_ELEMENTSМассив типа, он больше не может быть передан.
Вышеуказанные три типа представляют собой плотные (сжатые) массивы. Соответственно, это разреженный массив, помеченный какHOLEY_ELEMENTS, разреженные массивы также имеют три типа. любой типPACKEDможет перейти наHOLEY.
Почему два различия? Потому что с плотными массивами работать эффективнее, чем с разреженными.
Что такое плотный массив? По сути, это непрерывный стек блоков памяти.
Что такое разреженный массив? По сути, это связанный список хэшей блоков памяти.
Что такое разреженный массив на уровне языка? должен существоватьemptyмассив элементов.
let array = [0, 1, 2]; // PACKED_SMI_ELEMENTS
array.push(2.1); // PACKED_DOUBLE_ELEMENTS
array.push("3"); // PACKED_ELEMENTS
array[10] = "10"; // HOLEY_ELEMENTS
Чем ниже тип массива, тем хуже производительность. И переход типа массива будет идти только сверху вниз, а не снизу вверх. один отмечен какHOLEY_ELEMENTSмассив, даже еслиemptyПосле заполнения он также не будет помечен какPACKED_ELEMENTS.
Маленькие хитрости по оптимизации производительности
Эта небольшая часть оптимизации не имеет особого смысла, но она может значительно улучшить производительность.
Избегайте чтения за пределами длины массива
let array = [0, 1, 2];
array[10];
Эффект чтения данных за пределами длины массива заключается в выполнении дорогостоящего поиска по цепочке прототипов.
Где-то в jQuery есть зацикленный код для этого шаблона.
for (let i = 0, item; (item = items[i]) != null; i++) {
doSomething(item);
}
Смысл этого кода в том, чтобы прочитать все элементы массива, а затем прочитать еще один. пока не встретится неопределенный или нулевой элемент.
Есть три варианта, традиционныйfor, итерируемый объектfor-ofа такжеforEach. Нынешний V8,for-ofа такжеforEachпроизводительность иforдовольно.
Что еще хуже, значение находится в цепочке прототипов массива.
let arr = [1, 2, 3];
arr.__proto__ = { "10": "gg" };
console.log(arr[10]); // "gg"
Избегайте преобразования типа элемента
let array = [+0, 1, 2]; // PACKED_SMI_ELEMENTS
array.push(-0); // PACKED_DOUBLE_ELEMENTS
избегать использования-0,NaN,Infinity, потому что любой из их элементов приведет к тому, что тип массива станетPACKED_DOUBLE_ELEMENTS.
Предпочитайте массивы массивоподобным объектам
Хотя в JavaScript многие объекты очень похожи на массивы, и мы можем сами создавать массивоподобные объекты из объектов. Они обсуждались и демонстрировались выше. Но в итоге есть разница.
Например этот кусок кода:
let arrayLike = {};
arrayLike[0] = "a";
arrayLike[1] = "b";
arrayLike[2] = "c";
arrayLike.length = 3;
Array.prototype.forEach.call(arrayLike, (value, index) => {
console.log(`${index}: ${value}`);
});
Хотя нет проблем с запуском логики, это лучше, чем прямой вызов массиваforEachГораздо медленнее, потому что в V8,forEachУже сильно оптимизирован.
Решение для повышения производительности состоит в том, чтобы сначала преобразовать подобные массиву объекты в массивы, а затем вызвать методы массива. Хотя существует стоимость одного преобразования, оптимизация производительности взамен того стоит, особенно при выполнении большого количества операций с массивами.
const actualArray = Array.prototype.slice.call(arrayLike, 0);
actualArray.forEach((value, index) => {
console.log(`${index}: ${value}`);
});
Другая более распространенная ситуацияarguments.
Раньше для вывода параметров мы обычно делали это.
const logArgs = function() {
Array.prototype.forEach.call(arguments, (value, index) => {
console.log(`${index}: ${value}`);
});
};
logArgs("a", "b", "c");
Но в ES2015 мы можем использоватьrestпараметры решают эту проблему.
const logArgs = (...args) => {
args.forEach((value, index) => {
console.log(`${index}: ${value}`);
});
};
logArgs("a", "b", "c");
Теперь у нас нет абсолютно никаких причин использовать его напрямуюargumentsобъект. Если ваш код не будет работать на ES5.
избегать созданияHOLEY
В реальном кодировании разница в производительности при доступе к плотным и разреженным массивам настолько мала, что может быть незаметной или даже измеримой. Тем не менее, сохранение экстремальных привычек кодирования по-прежнему важно.
let array = new Array(3);
array[0] = 1;
array[1] = 2;
array[2] = 3;
Этот конструктор создастHOLEY_SMI_ELEMENTSмассив типов. В соответствии с введением V8 выше, переход типа массива будет только вниз, а не вверх. Итак, когда-то отмечен какHOLEY, всегда будетHOLEY. даже если этиemptyЗаполнение всего не помогает.
Лучший способ — использовать литерал для создания массива.
let array = [1, 2, 3];
Это может привести к оптимизации кода для некоторых операций над массивом.
Примечание автора: эта часть V8 не является оригинальным творением Учителя Цяня. Это перевод, оригинал взят изОфициальный блог V8Как видно выше, авторMathias Bynens. Прочитав ее, г-н Цянь подумал, что она хороша, поэтому добавил немного личного понимания и позаимствовал ее из моего блога. Заинтересованные студенты могут пойти посмотретьоригинальный.
Заключение Видя суть из абстракции: кунг-фу и данные
Содержание этой статьи представляет собой краткое введение в массив JavaScript.
На самом деле массив не сложен, это просто способ организации данных.
Все языки программирования имеют одинаковый тип данных. Числа, символы и логические значения. В человеческом понятии есть только эти три. Другие типы основаны на вариантах этих трех. Конечно, некоторые другие типы не включены в этот столбец, например, биты, буферы. Это не совсем типы данных. Поскольку они не могут соответствовать ничему в реальном мире, они относятся к типу данных компьютера. И другие способы организации данных, такие как массивы и объекты, представляют собой организацию и инкапсуляцию этих трех видов данных. Таким образом, они не являются базовыми типами данных, но их следует называть структурами данных.
Это очень похоже на бокс или Вин Чун. В мире бокса у людей только две руки, и разница в ударе не более чем направление и угол. Каждая секта дает им разные названия, но, в конечном счете, есть только три вида ударов: прямой удар, апперкот и размахивающий удар. И в Вин Чун тоже есть три оси – растопыренные. Это совпадает с тремя основными типами данных. Движение тела и разный порядок ударов, а также разная скорость и сила составляют нечто, называемое «комбинированным ударом» или «движением», которое является функцией массива или объекта. У него такой вкус, что Дао производит одно, одно производит два, два производят три, а три производят все вещи.
Будут развиваться боевые искусства. Король кунг-фу, пионер смешанных единоборств и величайший китаец 20-го века Брюс Ли основал Джит Кун До, также производное от традиционных китайских боевых искусств Вин Чун и смешанное с философскими идеями, западным боксом, каратэ, джиу-джитсу и другие навыки. .
Данные также могут быть получены, числа могут быть полученыint,float,double,long,bigint. Или по базе, производной, напримерint8,int16,int32,int64Такие вещи.
Каждый язык имеет свои собственные идеи, golang любит простоту, JavaScript любит сложность, C любит неограниченность, Java и C++ любят объектно-ориентированные идеи. Так же, как тай-чи, муай-тай, сумо, борьба и бокс, все они имеют свои собственные правила и идеи. Все они имеют свой собственный набор вещей, которые они считают правильными, таким образом образуя систему. Например, в некоторых традиционных китайских единоборствах считается, что «с ног вы теряете три очка». В ответ на свои собственные недостатки, недостатки и преимущества они делают что-то свое, и это является производным продуктом.
У программистов каждой фракции свой набор языковых систем, и разработчики Java позаботятся о них.float,double,int,long. Будет ли голанг касатьсяuint,int,floatи цифры. Программистов, занимающихся JavaScript, заботит толькоnumber. Но почти каждый программист знает что-то под названием JSON.
Все задумываются над вопросом, почему JSON так распространен в индустрии?
Есть две причины.
Один из них, потому что это достаточно просто и в то же время отвечает всем потребностям. JSON имеет только шесть типов данных: номер, строку, логический, объект, массив и нулевой, но он может удовлетворить все языки. Будь то запись файлов конфигурации или как формат взаимодействия данных.
二是因为它的全称叫做 JavaScript Object Notation。早期 Ajax 时代,数据交互很多都是使用 xml 的。但 xml 的写法过于繁琐,而且解析起来性能也不好。 JSON 出现,直接击溃 xml,成为标准。 Web2.0 至今,几乎 90%以上的网站都是使用 JSON。等到后来移动端时代来临,没有发明出更好的数据交互类型,而是直接采用了 JSON。 что насчет этого?一是历史原因,二是没必要。技术发展得快是因为老技术有痛点。而 JSON 并没有,当然也可能是痛点不明显,大家都默认接受了。哪怕是现在比较热门的新 API 交互语言 Graphql,仍然是使用 JSON 作为基础数据格式。
Итак, я надеюсь, что вы не ограничиваете себя системой типов языка. Мышление каждого языка несколько отличается, и характеристики тоже разные, и все они правильные. Это все стиль, а не баг. У каждого есть свой любимый стиль. Это как-то связано с личностью, возрастом, менталитетом и опытом. Некоторые люди, которым нравится тайский бокс, думают, что тай-чи — претенциозная вещь, не способная к реальному бою. Трудно отличить правильное от неправильного, с разными точками зрения, разными идеями и разными первоначальными намерениями. В мире программистов есть Java-программисты, которые считают JavaScript слишком запутанным, потому что он слишком гибкий, и есть JavaScript-программисты, которые думают, что Java слишком раздражает, потому что он слишком шаблонный. Это неизбежно. Также некоторым людям нравится JavaScript, а также Java, поэтому есть TypeScript.
Напоследок предупреждение всем:Чем больше вы практикуетесь, тем больше вы получаете.
Оригинальный адрес:Woohoo. Lu Zhenqian. top/Re под Stan…