«Метод массива» от детальной работы с массивом js до анализа array.js в v8

JavaScript
«Метод массива» от детальной работы с массивом js до анализа array.js в v8

предисловие

Я пишу вопросы по программированию по интервью недавно. Я часто пользуюсь массивами и часто хочу быть ленивым. Я использую методы, предоставляемые им, но я все еще нефессию в использовании методов массива, что приводит к написанию много мусора. Простой, Эффективный и элегантный 👊

Итак, ✍Эта статья основана на понимании характеристик массивов JavaScript, как следует из названия.

"Другие статьи:"

"Как реализовать общие методы массива самостоятельно через исходный код array.js в v8", если вы хотите улучшить свои навыки программирования, вы можете остаться и прочитать эту статью

"После прочтения вы получите 👏"

  • Больше ясности в общих методах работы с массивами
  • Как написать общие массивы вручную

Если вам это нравится, вы можете лайкнуть / подписаться и поддержать его.Я надеюсь, что вы можете прочитать эту статью и получить что-то.

Точка где нужно скачать код этой статьиGitHub

Начнем эту статью 🉑


备忘录

Основы массива

Если вы хотите написать методы массива вручную, вы должны сначала восполнить основы, и вы должны сначала иметь возможность использовать их API.

создать массив

			//字面量
            let demo = [1, 2, 3]
            // 构造器
            let demo1 = Array(),
                demo2 = Array(3),
                demo3 = Array(1,2,3),
                demo4 = new Array(1,2,3);

метод в конструкторе

Array.of()

Простое понимание заключается в том, чтобы создать экземпляр нового массива, вы можете увидеть разницу с конструктором массива

грамматика:

Array.of(element0[, element1[, ...[, elementN]]])

Применение:

Array.of(7);       // [7] 
Array.of(1, 2, 3); // [1, 2, 3]

Array(7);          // [ , , , , , , ]
Array(1, 2, 3);    // [1, 2, 3]

Разница между ними:Array.of(7)создать один элемент7массив иArray(7)Создайте пустой массив длиной 7 (**Примечание:** Это относится к массиву с 7 пустыми местами, а не к массиву из 7undefinedмассив компонентов).


Array.isArray()

Array.isArray()Используется для определения того, является ли переданное значениеArray.

Array.isArray([1, 2, 3]);  
// true
Array.isArray({foo: 123}); 
// false
Array.isArray("foobar");   
// false
Array.isArray(undefined);  
// false

Ручная реализация

			// Array.isArray
            if(!Array.isArray){
                Array.isArray = obj => Object.prototype.toString.call(obj) === '[object Array]'
            }

Чтобы судить о типе данных JS, вы можете посмотреть блог, который я написал ранее.Поговорим о принципе реализации typeof instanceof


Array.from()

Array.from()Метод создает новый экземпляр массива с неглубокой копией из массивоподобного или итерируемого объекта.

Array.from(arrayLike[, mapFn[, thisArg]])
параметр
  • arrayLike: требуется, вы можете передать 1, подобный массиву (аргументg) 2, итерируемый объект (набор, карта).
  • mapFn: необязательно, эквивалентно Array.from(arrayLike).map(mapFn, thisArg).
  • thisArg: необязательный, этот объект при выполнении функции обратного вызова mapFn. Очень полезно для развязки. Обрабатываемые данные могут быть отделены от объекта, дескриптор функции обработки определяется в thisArg, который используется для возврата результата после вызова дескриптора в mapFn.
Применение

String

			// Array.from()
            const demo = Array.from('123')
            console.log(demo) //[ 'a', 'b', 'c' ]

new Set()

			const Array_demo = Array.from(new Set([1,2,3,4,1,2,3]))
            console.log(Array_demo)  // [1,2,3,4]

new Map()

const map = new Map([[1, 2], [2, 4], [4, 8]]);
Array.from(map);
// [[1, 2], [2, 4], [4, 8]]

массивный

const fn = (function() {
    const demo = Array.from(arguments);
    console.log(demo);
})(1,2,3); // [ 1, 2, 3 ]

Развязка массива

			let fn = function () {
                console.log(arguments)
                const Arr_new = [].concat.apply([],arguments)
                return Array.from(new Set(Arr_new))
            }
            const   demo1 = [1, 2, 3, 4],
                    demo2 = [4,5,6,2,2,2],
                    demo3 = [1,2,3,4,2,2,3,4];
            console.log(fn(demo1,demo2,demo3))
            // [1,2,3,4,5,6]

В полной мере используйте третий параметр thisArg

		const obj = {
            handle: x => x * 4 
        }
        console.log(Array.from([11, 22, 33], function (x) {
            return this.handle(x)
        }, obj))
        // [44, 88, 132]
идеи
  • Определить, является ли arrayLike пустым
  • Судя по mapFn это конструктор, это конструктор, при каждом обходе пусть arr[i] = mapFn(iValue,i), когда не конструктор, arr[i] = iValue
  • Определить, существует ли thisArg, если он существует arr[i] = mapFn.call(thisArg, iValue,i)

Справочный исходный код находится в V8Строка 1763 array.js начинает путешествие Array.from

		/**
         * 实现Array.from
         * toInteger方法:返回一个整数
         * toLength方法: 保证len数字合法[0~Number.MAX_SAFE_INTEGER]
         * Number.MAX_SAFE_INTEGER = Math.pow(2,53) - 1
         * 判断arrayLike 为 空 抛出错误
         * mapFn非空并且不是构造函数抛出错误
         * 每次遍历arrayLike,如果mapFn存在, arr[i] = mapFn(iValue,i) 不存在的话 arr[i] = iValue
         * 判断thisArg是否存在,存在的话 arr[i] = mapFn.call(thisArg, iValue,i)
         * */
        Array.myfrom = (function () {
            const toStr = Object.prototype.toString
            const isCallable = fn => typeof fn === 'function' || toStr.call(fn) === '[object Function]'
            
            const toInteger = value => {
                const v = Number(value)
                if(isNaN(v))    return 0
                // 无穷大或者0 直接返回
                if(v === 0 || !isFinite(v)) return v
                return (v > 0 ? 1 : -1) * Math.floor(Math.abs(v))
            }
            // 最大的范围Number.MAX_SAFE_INTEGER
            const maxSafeInteger = Number.MAX_SAFE_INTEGER
            
            const toLength = value => {
                const len = toInteger(value)
                return Math.min(maxSafeInteger, Math.max(0, len))
            }
            return function myfrom (arrayLike/*, mapFn, thisArg*/) {
                const that = this
                if(arrayLike === null) throw new TypeError("Array.from requires an array-like object - not null or undefined")
                
                const items = Object(arrayLike)
                let thisArg = ''
                // 判断mapFn是否undefined, 这里最好不要直接使用undefined,因为undefined不是保留字,
                // 很有可能undefined是个值  最好用 void 0 或者 void undefined 
                const mapFn = arguments.length > 1 ? arguments[1] : void 0
                if( typeof mapFn !== 'undefined') {
                    // 接下来判断第二个参数是不是构造函数
                    if( !isCallable(mapFn) ) throw new TypeError("Array.from when provided mapFn must be a function")
                    if( arguments.length > 2) thisArg = arguments[2]
                }
                const len = toLength(items.length)
                const arr = isCallable(that) ? Object(new that(len)) : new Array(len)

                let i = 0,
                    iValue;
                while ( i < len) {
                    iValue = items[i]
                    if(mapFn) arr[i] = typeof thisArg === 'undefined' ? mapFn(iValue,i) : mapFn.call(thisArg, iValue, i)
                    else 
                        arr[i] = iValue
                    i++
                }
                arr.length = len
                return arr
            }
        })()

👍Должен сказать, что после реализации Array.from() я на самом деле много чего добился.


общий метод

Для облегчения запоминания и поиска основные методы разделены на три категории: Методы обхода массива, которые модифицируют исходный метод массива и возвращают новый метод массива.

метод обхода

Всего существует 12 способов обхода массива в js без изменения исходного массива:

 	ES5:
    forEach、every 、some、 filter、map、reduce、reduceRight、
    ES6:
    find、findIndex、keys、values、entries

forEach()

грамматика:

    array.forEach(callback(currentValue, index, arr), thisArg)

параметр:

 callback:为数组中每个元素执行的函数,该函数接收一至三个参数
 		  currentValue 数组中正在处理的当前元素
 		  index (可选)  数组中正在处理的当前元素的索引
 		  arr (可选)    forEach() 方法正在操作的数组
 thisArg      可选参数,当执行回调函数callback,用作this值

Давайте поговорим об использовании thisArg

function Counter() {
  this.sum = 0;
  this.count = 0;
}
Counter.prototype.add = function(array) {
  array.forEach(function(entry) {
    this.sum += entry;
    ++this.count;
  }, this);
  // ^---- Note
};

const obj = new Counter();
obj.add([2, 5, 9]);
obj.count;
// 3 === (1 + 1 + 1)
obj.sum;
// 16 === (2 + 5 + 9)

Очевидно, this, переданное в строке 9, определяет проблему, на которую указывает this в функции обратного вызова forEach.

В строке 14 obj вызывает метод add, поэтому this указывает на obj, то есть this в forEach указывает на объект obj.

**Примечание.** При использованииВыражение функции стрелкипередать параметры функции,thisArgАргументы игнорируются, поскольку стрелочные функции связаны лексическиthisстоимость

Взгляните на array.js в исходном коде v8.Строка 1258 начинает путешествие forEach.

Давайте попробуем сымитировать и написать один:

		/**
         * Array.prototype.forEach(callback, thisArg)
         * 除了抛出异常外,无法终止或者跳出forEach()循环
         * 遍历数组
         **/
        Array.prototype.myforEach = function (callback, thisArg) {
            if( this == null ) throw new TypeError("this is null or not defined")
            let newArr = Object(this)
            let len = newArr.length >>> 0
            if( typeof callback !== 'function' ) throw new TypeError(callback + ' is not a function');
            let thatArg = arguments.length >= 2 ? arguments[1] : void 0
            let k = 0

            while( k < len ) {
                
                if(k in newArr){ 
                    callback.call(thatArg, newArr[k], k, newArr);
                }
                k++
            }
            return void 0
        }

С точки зрения кода нужно обратить внимание:

  • Невозможно выйти из цикла на полпути, каждый раз, когда вы вызываете функцию обратного вызова, return может выйти только из этого обратного вызова.
  • Метод возвращает значение undefined, даже если вы возвращаете значение, оно бесполезно.
  • Что thisArg изменяет, так это this в функции обратного вызова, как видно из исходного кода, и если функция обратного вызова является стрелочной функцией, мы знаем, что стрелочная функция не может изменить это, поэтому thisArg будет проигнорирован

every()

определение:

Проверяет, все ли элементы в массиве проходят тест указанной функции. Он возвращает логическое значение.

грамматика:

    array.every(function(currentValue, index, arr), thisArg)

параметр:

 callback:为数组中每个元素执行的函数,该函数接收一至三个参数
 		  currentValue 数组中正在处理的当前元素
 		  index (可选)  数组中正在处理的当前元素的索引
 		  arr (可选)    every() 方法正在操作的数组
 thisArg      可选参数,当执行回调函数callback,用作this值

Применение:

function isBigEnough(element, index, array) {
  return element >= 10;
}
[12, 5, 8, 130, 44].every(isBigEnough);   // false
[12, 54, 18, 130, 44].every(isBigEnough); // true

Взгляните на array.js в исходном коде v8.С линии 1322 начинается каждое путешествие

		/**
         * Array.prototype.every(callback, thisArg)
         **/
        Array.prototype.myevery = function (callback, thisArg) {
            if( this == null ) throw new TypeError("this is null or not defined")
            let newArr = Object(this)
            let len = newArr.length >>> 0
            if( typeof callback !== 'function' ) throw new TypeError(callback + ' is not a function');
            let thatArg = arguments.length >= 2 ? arguments[1] : void 0
            let k = 0

            while( k < len ) {
                
                if(k in newArr){ 
                    let testResult = callback.call(thatArg, newArr[k], k, newArr);
                    if( !testResult ) return false
                }
                k++
            }
            return true
        }

С точки зрения кода нужно обратить внимание:

  • В случае пустого массива, пока первый параметр является функцией обратного вызова, все возвращает true
  • Чтобы возвращать true каждый раз, возвращайте true в конце, иначе false
  • Если параметр thisArg присутствует, тоcallbackкогда звонятthisзначение, глобальный объект в нестрогом режиме, переданный в строгом режимеundefined, видетьthisВход.
  • каждый не изменяет исходный массив
  • everyИтерация по диапазону элементов в первом вызовеcallbackЭто было определено ранее. вызовeveryЭлементы, добавленные в массив позже, не будутcallbackдоступ к. Если элементы, присутствующие в массиве, изменены, они переходят вcallbackЗначениеeveryдоступ к их стоимости в данный момент. Доступ к удаленным элементам или элементам, которым никогда не присваивалось значение, невозможен.

some

определение:

Проверяет, проходит ли хотя бы один элемент в массиве предоставленный функциональный тест. Возвращает значение типа Boolean

грамматика:

    array.some(function(currentValue, index, arr), thisArg)

параметр:

 callback:为数组中每个元素执行的函数,该函数接收一至三个参数
 		  currentValue 数组中正在处理的当前元素
 		  index (可选)  数组中正在处理的当前元素的索引
 		  arr (可选)    some() 方法正在操作的数组
 thisArg      可选参数,当执行回调函数callback,用作this值

Применение:

function isBiggerThan10(element, index, array) {
  return element > 10;
}
[2, 5, 8, 1, 4].some(isBiggerThan10);  // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true

//此例中为模仿 includes()  方法, 若元素在数组中存在, 则回调函数返回值为 true :
var fruits = ['apple', 'banana', 'mango', 'guava'];

function checkAvailability(arr, val) {
  return arr.some(function(arrVal) {
    return val === arrVal;
  });
}

checkAvailability(fruits, 'kela');   // false
checkAvailability(fruits, 'banana'); // true

Взгляните на array.js в исходном коде v8.Строка 1298 начинает какое-то путешествие

		/**
         * 测试数组中是不是至少有1个元素通过了被提供的函数测试
         * Array.prototype.some(callback, thisArg)
         **/
        Array.prototype.mysome = function (callback, thisArg) {
            if (this == null) throw new TypeError("this is null or not defined")
            let newArr = Object(this)
            let len = newArr.length >>> 0
            if (typeof callback !== 'function') throw new TypeError(callback + ' is not a function');
            let thatArg = arguments.length >= 2 ? arguments[1] : void 0

            for (let i = 0; i < len; i++) {
                if (i in newArr && callback.call(thatArg, newArr[i], i, newArr))
                    return true
            }
            return false
        }

С точки зрения кода нужно обратить внимание:

  • некоторые не меняют исходный массив
  • При тестировании с пустым массивом в любом случае возвращаетсяfalse
  • Если ваша callback-функция не имеет возвращаемого значения, она каждый раз не определена, а также возвращается результат вызова some в конце.false
  • Передача thisArg, значение this в функции обратного вызова, зависит от правила указания this.

filter

определение:

Создает новый массив, содержащий все элементы теста, реализованного предоставленной функцией.

грамматика:

let newArray = array.filter(function(currentValue, index, arr), thisArg)

параметр:

 callback:为数组中每个元素执行的函数,该函数接收一至三个参数
 		  currentValue 数组中正在处理的当前元素
 		  index (可选)  数组中正在处理的当前元素的索引
 		  arr (可选)    filter() 方法正在操作的数组
 thisArg      可选参数,当执行回调函数callback,用作this值

Применение:

function isBigEnough(element) {
  return element >= 10;
}
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// filtered is [12, 130, 44] 

var fruits = ['apple', 'banana', 'grapes', 'mango', 'orange'];

/**
 * Array filters items based on search criteria (query)
 */
function filterItems(query) {
  return fruits.filter(function(el) {
      return el.toLowerCase().indexOf(query.toLowerCase()) > -1;
  })
}

console.log(filterItems('ap')); // ['apple', 'grapes']
console.log(filterItems('an')); // ['banana', 'mango', 'orange']

Взгляните на array.js в исходном коде v8.Строка 1245 начинает путь к фильтру

/**
         * 创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。 
         * Array.prototype.filter(callback, thisArg)
         *
         */
        Array.prototype.myfilter = function (callback, thisArg) {
            if (this == null) throw new TypeError("this is null or not defined")
            let newArr = Object(this)
            let len = newArr.length >>> 0
            if (typeof callback !== 'function') throw new TypeError(callback + ' is not a function');
            let thatArg = arguments.length >= 2 ? arguments[1] : void 0,
                resultArr = new Array(len),
                count = 0

            for (let i = 0; i < len; i++) {
                if (i in newArr) {
                    if (typeof thatArg === 'undefined' && callback(newArr[i], i, newArr)) 
                        resultArr[count++] = newArr[i]
                    if (typeof thatArg !== 'undefined' && callback.call(thatArg, newArr[i], i, newArr)) 
                        resultArr[count++] = newArr[i]
                }
            }
            resultArr.length = count
            return resultArr
        }

С точки зрения кода нужно обратить внимание:

  • Пользовательская функция обратного вызова должна иметь логическое возвращаемое значение. Если она не записывает возвращаемое значение по умолчанию, равное undefined, тогда логическое значение должно быть ложным.
  • Не изменяет исходный массив, а возвращает новый массив, содержащий все элементы теста, реализованного предоставленной функцией.
  • Возвращает пустой массив, если не передано ни одного элемента
  • filterне изменяет исходный массив, он возвращает новый отфильтрованный массив
  • filterИтерация по диапазону элементов в первом вызовеcallbackЭто было определено ранее. вызовfilterЭлементы, добавленные в массив позже, не будутfilterпройти к. Если существующие элементы были изменены, они переходят вcallbackЗначениеfilterПерейдите к их значению на данный момент. Элементы, которые удалены или которым никогда не присваивалось значение, не просматриваются.
  • еслиfilterобеспечитьthisArgпараметр, он будет использоваться какcallbackкогда звонятthisстоимость. иначе,callbackизthisЗначением будет глобальный объект в нестрогом режиме и в строгом режиме.undefined.callbackФункция, наконец, наблюдаетthisЗначения основаны на обычномПравила для «этого» с точки зрения функцииопределенный.
  • Обратите особое внимание на указатель this в функции стрелки.

map

определение:

Создает новый массив, результатом которого является то, что каждый элемент массива является возвращаемым значением одного вызова предоставленной функции обратного вызова.

грамматика:

let newArray = array.map(function(currentValue, index, arr), thisArg)

параметр:

 callback:为数组中每个元素执行的函数,该函数接收一至三个参数
 		  currentValue 数组中正在处理的当前元素
 		  index (可选)  数组中正在处理的当前元素的索引
 		  arr (可选)    map() 方法正在操作的数组
 thisArg      可选参数,当执行回调函数callback,用作this值

Применение:

//数组中每个元素的平方根
var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt);
// roots的值为[1, 2, 3], numbers的值仍为[1, 4, 9]

var numbers = [1, 4, 9];
var doubles = numbers.map(function(num) {
  return num * 2;
});

// doubles数组的值为: [2, 8, 18]
// numbers数组未被修改: [1, 4, 9]

//演示如何在一个 String  上使用 map 方法获取字符串中每个字符所对应的 ASCII 码组成的数组:
var map = Array.prototype.map
var a = map.call("Hello World", function(x) { 
  return x.charCodeAt(0); 
})
// a的值为[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]

Взгляните на array.js в исходном коде v8.Строка 1333 начинает путешествие по карте.

/**
         * 一个由原数组每个元素执行回调函数的结果组成的新数组 
         * Array.prototype.map(callback, thisArg)
         *
         */
        Array.prototype.mymap = function (callback, thisArg) {
            if (this == null) throw new TypeError("this is null or not defined")
            let newArr = Object(this)
            let len = newArr.length >>> 0
            if (typeof callback !== 'function') throw new TypeError(callback + ' is not a function');
            let thatArg = arguments.length >= 2 ? arguments[1] : void 0,
                resultArr = new Array(len),
                mappedValue

            for (let i = 0; i < len; i++) {
                if (i in newArr) {
                    // 可能会有疑惑的地方
                    mappedValue = callback.call(thatArg, newArr[i], i, newArr)
                    resultArr[i] = mappedValue
                }
            }
            return resultArr
        }

Место, где могут быть сомнения, это строка 17. Почему вы можете написать это прямо? Вам не нужно рассматривать случай, что thisArg равен void 0. Я рассматривал это на случай, но подумаем об этом позже, даже если это значение undefined, вы Карта выполняет функцию обратного вызова Это значение функции обратного вызова является окном в нестрогом режиме.

		var numbers = [1, 4, 9];
        var doubles = numbers.map(function (num) {
            console.log(this)    // window
            return num * 2;
        }, void 0);

👆 Когда вы запустите код в консоли, вы обнаружите, что передается thisArg. Когда значение не определено, результатом остается окно. Конечно, оно не определено в строгом режиме. Об этом остается подумать читателю. .

С точки зрения кода нужно обратить внимание:

  • mapне изменяет сам исходный массив, вызвавший его (конечно, вcallbackИзмените исходный массив при выполнении)
  • Когда функция обратного вызова не возвращает значение, каждое значение последнего нового массива не определено.
  • thisЗначение в конечном счете относительноcallbackНаблюдаемость функции основана наthisПравила, то есть это указывает на проблему
  • потому чтоmapСоздайте новый массив, если вы не собираетесь использовать возвращенный новый массив, но используетеmapпротиворечит первоначальному замыслу дизайна, пожалуйста, используйтеforEachилиfor-ofальтернатива.
  • mapОбласть действия метода для обработки элементов массива находится вcallbackМетод определяется перед первым вызовом. передачаmapЭлементы массива, добавленные после метода, не будутcallbackдоступ. Если существующий элемент массива изменился, то передается вcallbackЗначениеmapЗначение при доступе к этому элементу.

reduce

определение:

Выполняет одно из предоставленных вами действий над каждым элементом в массивеreducerФункция (выполняемая в порядке возрастания), которая объединяет свои результаты в одно возвращаемое значение.

грамматика:

let result = array.reduce(callback(accumulator, currentValue, currentIndex, array), initialValue)

параметр:

 callback:为数组中每个元素执行的函数,该函数接收一至4个参数
 		    accumulator 累计器
			currentValue 当前值
			currentIndex 当前索引
			array 数组
 initialValue      
作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。

Применение:

Вариант использования - это простое использование, более продвинутое использование сокращения, в конце есть ссылка на ссылку👇

const arr = [3, 5, 1, 4, 2];
const a = arr.reduce((t, v) => t + v);
// 等同于
const b = arr.reduce((t, v) => t + v, 0);

Посмотрите, как это объясняет gif-анимация👇

Это может быть самый простой способ его использования, давайте распространять свое мнение 😼

// 功能型函数通道
const double = x => x + x;
const triple = x => 3 * x;
const quadruple = x => 4 * x;

// Function composition enabling pipe functionality
const pipe = (...functions) => input => functions.reduce(
    (acc, fn) => fn(acc),
    input
);

// Composed functions for multiplication of specific values
const multiply6 = pipe(double, triple);
const multiply9 = pipe(triple, triple);
const multiply16 = pipe(quadruple, quadruple);
const multiply24 = pipe(double, triple, quadruple);

// Usage
multiply6(6); // 36
multiply9(9); // 81
multiply16(16); // 256
multiply24(10); // 240

Иногда использование сокращения действительно делает разработку более эффективной✊

Взгляните на array.js в исходном коде v8**.Строка 1505 начинает путь сокращения

/**
         * 对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值
         * Array.prototype.reduce(callback, initialValue)
         *
         */
        Array.prototype.myreduce = function (callback /*, initialValue*/ ) {
            if (this == null) throw new TypeError("this is null or not defined")
            let newArr = Object(this)
            let len = newArr.length >>> 0
            if (typeof callback !== 'function') throw new TypeError(callback + ' is not a function');
            let initialValue,
                k = 0

            if (arguments.length >= 2) {
                initialValue = arguments[1]
            } else {
                while (k < len && !(k in newArr))
                    k++
                if (k >= len)
                    throw new TypeError('Reduce of empty array with no initial value')
                initialValue = newArr[k++]
            }

            for (let i = k; i < len; i++) {
                if (i in newArr) {
                    initialValue = callback(initialValue, newArr[i], i, newArr)
                }
            }
            return initialValue
        }

С точки зрения кода нужно обратить внимание:

  • Когда функция обратного вызова выполняется в первый раз,accumulatorа такжеcurrentValueЕсть два случая для значения : если вы вызываетеreduce()предоставляется, когдаinitialValue,accumulatorстоимостьinitialValue,currentValueПринимает первое значение в массиве, если не указаноinitialValue,Такaccumulatorвзять первое значение в массиве,currentValueВозьмите второе значение в массиве.
  • если не предусмотреноinitialValue, reduce выполнит метод обратного вызова, начиная с индекса 1, пропуская первый индекс. если предусмотреноinitialValue, начиная с индекса 0.
  • если массив пуст и не указанinitialValue, броситTypeError.
  • Если в массиве только один элемент (независимо от позиции) и нетinitialValue, или предоставитьinitialValueно массив пуст, то будет возвращено это уникальное значение иcallbackвыполняться не будет.

Функция редукции слишком мощная, и те, кому интересно, могут хорошенько на нее взглянуть✊

Конечно, благодаря этому анализу кода, я думаю, вы лучше понимаете принцип сокращения.


reduceRight

Накопить справа налево, аналогично уменьшению, реализация исходного кода будет естественно ✍

определение:

Принимая функцию как одно значение для каждого значения (справа налево) как аккумулятор и массив. Суммируйте результаты как одно возвращаемое значение.

грамматика:

let result = array.reduceRight(callback(accumulator, currentValue, currentIndex, array), initialValue)

параметр:

 callback:为数组中每个元素执行的函数,该函数接收一至4个参数
 		    accumulator 上一次调用回调函数时,回调函数返回的值。
			currentValue 当前值
			currentIndex 当前索引
			array 数组
 initialValue      
首次调用 callback 函数时,累加器 accumulator 的值。如果未提供该初始值,则将使用数组中的最后一个元素,并跳过该元素。

Применение:

Вот разница между сокращением и уменьшением 👏

var a = ['1', '2', '3', '4', '5']; 
var left  = a.reduce(function(prev, cur)      { return prev + cur; }); 
var right = a.reduceRight(function(prev, cur) { return prev + cur; }); 

console.log(left);  // "12345"
console.log(right); // "54321"

Взгляните на array.js в исходном коде v8**.Строка 1505 начинает путешествие по пути reduceRight.

Если это реализовано, возьмите указательный индекс и смоделируйте от последнего бита массива к началу 😹 Просто обратите внимание на граничное значение

find findIndex

Этот метод был добавлен в спецификацию ECMAScript 6 и может отсутствовать в некоторых реализациях.

определение:

**find:** Возвращает значение первого элемента в массиве, который удовлетворяет предоставленной тестовой функции. в противном случае вернутьсяundefined.

индекс поиска:массив, предоставив первый элемент тестовой функциипоказатель. В противном случае вернуть -1.

грамматика:

let ele = array.find(function(elemnet, index, arr), thisArg)
let eleIndex = array.findIndex(function(elemnet, index, arr), thisArg)

параметр:

Оба грамматически похожи

 callback:为数组中每个元素执行的函数,该函数接收一至三个参数
 		  elemnet 数组中正在处理的当前元素
 		  index (可选)  数组中正在处理的当前元素的索引
 		  arr (可选)     find方法正在操作的数组
 thisArg      可选参数,当执行回调函数callback,用作this值

найти использование:

//寻找数组中的质数
function isPrime(element, index, array) {
  var start = 2;
  while (start <= Math.sqrt(element)) {
    if (element % start++ < 1) {
      return false;
    }
  }
  return element > 1;
}

console.log([4, 6, 8, 12].find(isPrime)); // undefined, not found
console.log([4, 5, 8, 12].find(isPrime)); // 5

Использование findIndex:

//找数组中首个质数元素的索引 不存在素数返回-1
function isPrime(element, index, array) {
  var start = 2;
  while (start <= Math.sqrt(element)) {
    if (element % start++ < 1) {
      return false;
    }
  }
  return element > 1;
}

console.log([4, 6, 8, 12].findIndex(isPrime)); // -1, not found
console.log([4, 6, 7, 12].findIndex(isPrime)); // 2

Взгляните на array.js в исходном коде v8**.1633 линия начинается найти тур

		/**
         * 返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined
         * Array.prototype.find(callback, thisArg)
         *
         */
        Array.prototype.myfind = function (callback /*, thisArg */ ) {
            if (this == null) throw new TypeError("this is null or not defined")
            let newArr = Object(this)
            let len = newArr.length >>> 0
            if (typeof callback !== 'function') throw new TypeError(callback + ' is not a function');

            let thatArg = arguments.length >= 2 ? arguments[1] : void 0

            for (let i = 0; i < len; i++) {
                if (i in newArr && callback.call(thatArg, newArr[i], i, newArr))
                    return newArr[i]
            }
            return void 0
        }

Принцип работы функции findIndex точно такой же, а возвращаемым значением является просто индекс❗

С точки зрения кода нужно обратить внимание:

  • Метод find не изменяет исходный массив
  • в первый звонокcallbackфункция будет определять диапазон индексов элементов, поэтому вfindНовые элементы, добавленные в массив после начала выполнения метода, не будутcallbackфункция для доступа.
  • Если один из массивов не былcallbackЗначение элемента, к которому обращается функция, равноcallbackфункция изменилась, то когдаcallbackКогда функция обращается к нему, его значением будет текущее значение, полученное в соответствии с его индексом в массиве. Доступ к удаленному элементу по-прежнему будет осуществляться, но его возвращаемое значение уже не определено.
  • Я много читал о функции поиска, и лично я не думаю, что она указана.thisArgДля параметров указатель this функции обратного вызова не всегда не определен, что более разумно.это соответствует этому правилу указания.

keys & values & entries

определение:

keys()Метод возвращает массив, содержащий каждый ключ индекса в массиве.**Array Iterator**объект.

values()метод возвращает новыйArray Iteratorобъект, который содержит значение для каждого индекса массива

entries()метод возвращает новыйArray IteratorОбъект содержит индекс массива для каждой ключевой / значение-пар.

грамматика:

arr.entries()

Применение:

Использование трех аналогично, давайте возьмем один из них в качестве примера.

const array1 = ['a', 'b', 'c'];
const iterator1 = array1.entries();
const iterator2 = array1.values();
const iterator3 = array1.keys();
console.log(iterator1);
/*Array Iterator {}
         __proto__:Array Iterator
         next:ƒ next()
         Symbol(Symbol.toStringTag):"Array Iterator"
         __proto__:Object
*/	

iterator.next()

var arr = ["a", "b", "c"]; 
var iterator = arr.entries();
console.log(iterator.next());

/*{value: Array(2), done: false}
          done:false
          value:(2) [0, "a"]
           __proto__: Object
*/
// iterator.next()返回一个对象,对于有元素的数组,
// 是next{ value: Array(2), done: false };
// next.done 用于指示迭代器是否完成:在每次迭代时进行更新而且都是false,
// 直到迭代器结束done才是true。
// next.value是一个["key","value"]的数组,是返回的迭代器中的元素值。

использоватьдля… изцикл

var arr = ["a", "b", "c"];
var iterator = arr.entries();
// undefined

for (let e of iterator) {
    console.log(e);
}

// [0, "a"] 
// [1, "b"] 
// [2, "c"]

Контента много, надеюсь вы сможете ознакомиться 🉑


Изменить исходный метод массива

splice

определение:

Измените массив, удалив или заменив существующие элементы или добавив новые элементы на место, и верните измененное содержимое в виде массива,Обратите внимание, что этот метод изменит исходный массив

грамматика:

array.splice(start,deleteCount,item1,.....,itemX)

параметр:

 start: 指定修改的开始位置(从0计数)
		1. 如果超出了数组的长度,则从数组末尾开始添加内容
		2. 如果是负值,则表示从数组末位开始的第几位(从-1计数,这意味着-n是倒数第n个元素,并且等价于array.length-n)
		3. 如果负数的绝对值大于数组的长度,则表示开始位置为第0位
deleteCount(可选) : 整数,表示要移除的数组元素个数	
		1. 如果 deleteCount 大于 start 之后的元素的总数,则从 start 后面的元素都将被			删除(含第 start 位)
		2. 如果 deleteCount 被省略了,或者它的值大于等于array.length - start(也就是		   说,如果它大于或者等于start之后的所有元素的数量),那么start之后数组的所有元素都会被删除。
		3. 如果 deleteCount 是 0 或者负数,则不移除元素。这种情况下,至少应添加一个新		   元素。
item1, item2, ...(可选) 
要添加进数组的元素,从start 位置开始。如果不指定,则 splice() 将只删除数组元素。

Применение:

//从第 2 位开始删除 0 个元素,插入“drum”
var myFish = ["angel", "clown", "mandarin", "sturgeon"];
var removed = myFish.splice(2, 0, "drum");

// 运算后的 myFish: ["angel", "clown", "drum", "mandarin", "sturgeon"]
// 被删除的元素: [], 没有元素被删除
// 从第 2 位开始删除 0 个元素,插入“drum” 和 "guitar"
var removed2 = myFish.splice(2, 0, 'drum', 'guitar');
// 运算后的 myFish: ["angel", "clown", "drum", "guitar", "mandarin", "sturgeon"]
// 被删除的元素: [], 没有元素被删除

Удалить 1 элемент из позиции 2, вставьте «труба»

var myFish = ['angel', 'clown', 'drum', 'sturgeon'];
var removed = myFish.splice(2, 1, "trumpet");

// 运算后的 myFish: ["angel", "clown", "trumpet", "sturgeon"]
// 被删除的元素: ["drum"]

Удалите 2 элемента, начиная с позиции 0, вставьте «попугай», «анемон» и «синий».

var myFish = ['angel', 'clown', 'trumpet', 'sturgeon'];
var removed = myFish.splice(0, 2, 'parrot', 'anemone', 'blue');

// 运算后的 myFish: ["parrot", "anemone", "blue", "trumpet", "sturgeon"]
// 被删除的元素: ["angel", "clown"]

Удалить 1 элемент, начиная со 2-й последней позиции

var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
var removed = myFish.splice(-2, 1);

// 运算后的 myFish: ["angel", "clown", "sturgeon"]
// 被删除的元素: ["mandarin"]

Удалить все элементы, начиная с позиции 2

var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
var removed = myFish.splice(2);

// 运算后的 myFish: ["angel", "clown"]
// 被删除的元素: ["mandarin", "sturgeon"]

Взгляните на array.js в исходном коде v8**.Линия 876 начинает сращивание

Это должна быть простая симуляция, единственное, что раздражает, это граничное значение


sort

определение:

Сортирует элементы массива и возвращает массив,Обратите внимание, что этот метод изменит исходный массив

грамматика:

arr.sort([compareFunction])

параметр:

 compareFunction 可选
1. 用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序。
2. 指明了compareFunction,
3. 如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;
4. 如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变。
5. 如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前。

Применение:

var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
  return a - b;
});
console.log(numbers);

//也可以写成:
var numbers = [4, 2, 5, 1, 3]; 
numbers.sort((a, b) => a - b); 
console.log(numbers);

// [1, 2, 3, 4, 5]

Вроде персонажей не ASCII

//当排序非 ASCII 字符的字符串(如包含类似 e, é, è, a, ä 等字符的字符串)。
//一些非英语语言的字符串需要使用 String.localeCompare。这个函数可以将函数排序到正确的顺序。
var items = ['réservé', 'premier', 'cliché', 'communiqué', 'café', 'adieu'];
items.sort(function (a, b) {
  return a.localeCompare(b);
});

// items is ['adieu', 'café', 'cliché', 'communiqué', 'premier', 'réservé']

Сортировка — это наука, и в ней много содержания, например, сложность события и сложность алгоритма по пространству, которые будут обновлены позже.


pop

определение:

Удаляет последний элемент из массива и возвращает значение этого элемента. Этот метод изменяет длину массива.

грамматика:

arr.pop()
//从数组中删除的元素(当数组为空时返回undefined)。

описывать:

1. pop 方法从一个数组中删除并返回最后一个元素。
2. pop方法根据 length属性来确定最后一个元素的位置。
3. 如果不包含length属性或length属性不能被转成一个数值,会将length置为0,并返回undefined。
4. 如果你在一个空数组上调用 pop(),它返回  undefined。

Применение:

let myFish = ["angel", "clown", "mandarin", "surgeon"];

let popped = myFish.pop();

console.log(myFish); 
// ["angel", "clown", "mandarin"]

console.log(popped); 
// surgeon

🚀🚀🚀 были


shift

определение:

удалить из массиваПервыйэлемент и возвращает значение этого элемента. Этот метод изменяет длину массива.

грамматика:

arr.shift()
//从数组中删除的元素; 如果数组为空则返回undefined 。 

описывать:

1. shift 方法移除索引为 0 的元素(即第一个元素),并返回被移除的元素,其他元素的索引值随之减 1
2. 如果 length 属性的值为 0 (长度为 0),则返回 undefined。
3. shift 方法并不局限于数组:这个方法能够通过 call 或 apply 方法作用于类似数组的对象上
4. 对于没有 length 属性(从0开始的一系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何意义。

Применение:

let myFish = ['angel', 'clown', 'mandarin', 'surgeon'];

console.log('调用 shift 之前: ' + myFish);
// "调用 shift 之前: angel,clown,mandarin,surgeon"

var shifted = myFish.shift(); 

console.log('调用 shift 之后: ' + myFish); 
// "调用 shift 之后: clown,mandarin,surgeon" 

console.log('被删除的元素: ' + shifted); 
// "被删除的元素: angel"

🚀🚀🚀 Не должно быть сложностей


unshift

определение:

Добавить один или несколько элементов в массивначалои возвращает массивновая длина (т.метод изменения исходного массива

грамматика:

arr.unshift(element1, ..., elementN)
// element要添加到数组开头的元素或多个元素。

описывать:

1. unshift 方法会在调用它的类数组对象的开始位置插入给定的参数。
2. unshift 特意被设计成具有通用性;这个方法能够通过 call 或 apply 方法作用于类数组对象上
3. 不过对于没有 length 属性(代表从0开始的一系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何意义。
4. 注意, 如果传入多个参数,它们会被以块的形式插入到对象的开始位置,它们的顺序和被作为参数传入时的顺序一致
5. ,传入多个参数调用一次 unshift ,和传入一个参数调用多次 unshift (例如,循环调用),它们将得到不同的结果。例如:

Применение:

let arr = [4,5,6];
arr.unshift(1,2,3);
console.log(arr); // [1, 2, 3, 4, 5, 6]

arr = [4,5,6]; // 重置数组
arr.unshift(1);
arr.unshift(2);
arr.unshift(3);
console.log(arr); // [3, 2, 1, 4, 5, 6]

см. другой пример

arr.unshift(0); // result of the call is 3, which is the new array length
// arr is [0, 1, 2]

arr.unshift(-2, -1); // the new array length is 5
// arr is [-2, -1, 0, 1, 2]

arr.unshift([-4, -3]); // the new array length is 6
// arr is [[-4, -3], -2, -1, 0, 1, 2]

arr.unshift([-7, -6], [-5]); // the new array length is 8
// arr is [ [-7, -6], [-5], [-4, -3], -2, -1, 0, 1, 2 ]

🚀🚀🚀 Не должно быть сложностей


push

определение:

Добавляет один или несколько элементов в конец массива и возвращает новую длину массива.

грамматика:

arr.push(element1, ..., elementN)
// element要添加到数组末尾的元素或多个元素。
// 放回值:当调用该方法时,新的 length 属性值将被返回。

описывать:

1. push 方法具有通用性。该方法和 call() 或 apply() 一起使用时,可应用在类似数组的对象上。
2. push 方法根据 length 属性来决定从哪里开始插入给定的值。
3. 如果 length 不能被转成一个数值,则插入的元素索引为 0,包括 length 不存在时。当 length 不存在时,将会创建它。

Применение:

добавить элемент в массив

var sports = ["soccer", "baseball"];
var total = sports.push("football", "swimming");

console.log(sports); 
// ["soccer", "baseball", "football", "swimming"]

console.log(total);  
// 4

Используйте объекты, такие как массивы

var obj = {
    length: 0,

    addElem: function addElem (elem) {
        // obj.length is automatically incremented 
        // every time an element is added.
        [].push.call(this, elem);
    }
};

// Let's add some empty objects just to illustrate.
obj.addElem({});
obj.addElem({});
console.log(obj.length);
// → 2
//注意,尽管 obj 不是数组,但是 push 方法成功地使 obj 的 length 属性增长了,就像我们处理一个实际的数组一样。

Поехали, сложностей в уходе за ней возникнуть не должно🚀🚀🚀


reverse

определение:

Меняет местами элементы в массиве и возвращает массив. Первый элемент массива становится последним, а последний элемент массива становится первым. Этот метод изменяет исходный массив.

грамматика:

arr.reverse()
// 放回值:颠倒后的数组

описывать:

1. reverse 方法颠倒数组中元素的位置,改变了数组,并返回该数组的引用。
2. reverse方法是特意类化的;此方法可被 called 或 applied于类似数组对象。
3. 对象如果不包含反映一系列连续的、基于零的数值属性中的最后一个长度的属性,则该对象可能不会以任何有意义的方式运行。

Применение:

Обратные элементы в массиве

const a = [1, 2, 3];

console.log(a); // [1, 2, 3]

a.reverse(); 

console.log(a); // [3, 2, 1]

Обратные элементы в массиве, подобном массиву

onst a = {0: 1, 1: 2, 2: 3, length: 3};

console.log(a); // {0: 1, 1: 2, 2: 3, length: 3}

Array.prototype.reverse.call(a); //same syntax for using apply()

console.log(a); // {0: 3, 1: 2, 2: 1, length: 3}

copyWithin

определение:

Поверхностно копирует часть массива в другое место в том же массиве и возвращает его без изменения длины исходного массива.

грамматика:

    array.copyWithin(target, start = 0, end = this.length)
// 放回值:改变后的数组。

параметр:

target
1. 0 为基底的索引,复制序列到该位置。如果是负数,target 将从末尾开始计算。
2. 如果 target 大于等于 arr.length,将会不发生拷贝。如果 target 在 start 之后,复制的序列将被修改以符合 arr.length。

start
1. 0 为基底的索引,开始复制元素的起始位置。如果是负数,start 将从末尾开始计算。
2. 如果 start 被忽略,copyWithin 将会从0开始复制。
end
1. 0 为基底的索引,开始复制元素的结束位置。copyWithin 将会拷贝到该位置,但不包括 end 这个位置的元素。如果是负数, end 将从末尾开始计算。
2. 如果 end 被忽略,copyWithin 方法将会一直复制至数组结尾(默认为 arr.length)。

Уведомление:

1. 参数 target、start 和 end 必须为整数。
2. 如果 start 为负,则其指定的索引位置等同于 length+start,length 为数组的长度。end 也是如此。
3. copyWithin 是一个可变方法,它不会改变 this 的长度 length,但是会改变 this 本身的内容,且需要时会创建新的属性。

Применение:

const a = [1, 2, 3];
[1, 2, 3, 4, 5].copyWithin(-2)
// [1, 2, 3, 1, 2]

[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]

[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]

[1, 2, 3, 4, 5].copyWithin(-2, -3, -1)
// [1, 2, 3, 3, 4]

[].copyWithin.call({length: 5, 3: 1}, 0, 3);
// {0: 1, 3: 1, length: 5}
console.log(a); // [1, 2, 3]

a.reverse(); 

console.log(a); // [3, 2, 1]

Я не могу использовать этот метод для решения проблемы, у меня от этого голова болит❌


fill

определение:

Заполняет все элементы массива от начального до конечного индекса фиксированным значением. Индекс завершения не включен.

грамматика:

    arr.fill(value, start, end )
// 放回值:修改后的数组。

параметр:

value
1. 用来填充数组元素的值。

start (可选)
1. 起始索引,默认值为0。

end  (可选)
1. 终止索引,默认值为 this.length。

описывать:

1. 如果 start 是个负数, 则开始索引会被自动计算成为 length+start,其中 length 是 this 对象的 length 属性值
2. fill 方法故意被设计成通用方法, 该方法不要求 this 是数组对象。
3. fill 方法是个可变方法, 它会改变调用它的 this 对象本身, 然后返回它, 而并不是返回一个副本。
4. 当一个对象被传递给 fill方法的时候, 填充数组的是这个对象的引用。 

Применение:

[1, 2, 3].fill(4);               // [4, 4, 4]
[1, 2, 3].fill(4, 1);            // [1, 4, 4]
[1, 2, 3].fill(4, 1, 2);         // [1, 4, 3]
[1, 2, 3].fill(4, 1, 1);         // [1, 2, 3]
[1, 2, 3].fill(4, 3, 3);         // [1, 2, 3]
[1, 2, 3].fill(4, -3, -2);       // [4, 2, 3]
[1, 2, 3].fill(4, NaN, NaN);     // [1, 2, 3]
[1, 2, 3].fill(4, 3, 5);         // [1, 2, 3]
Array(3).fill(4);                // [4, 4, 4]
[].fill.call({ length: 3 }, 4);  // {0: 4, 1: 4, 2: 4, length: 3}
// Objects by reference.
var arr = Array(3).fill({}) // [{}, {}, {}];
// 需要注意如果fill的参数为引用类型,会导致都执行都一个引用类型
// 如 arr[0] === arr[1] 为true
arr[0].hi = "hi"; // [{ hi: "hi" }, { hi: "hi" }, { hi: "hi" }]

Взгляните на array.js в исходном коде v8.Линия 1700 начинает заправку

if (!Array.prototype.fill) {
  Object.defineProperty(Array.prototype, 'fill', {
    value: function(value) {

      // Steps 1-2.
      if (this == null) {
        throw new TypeError('this is null or not defined');
      }

      var O = Object(this);

      // Steps 3-5.
      var len = O.length >>> 0;

      // Steps 6-7.
      var start = arguments[1];
      var relativeStart = start >> 0;

      // Step 8.
      var k = relativeStart < 0 ?
        Math.max(len + relativeStart, 0) :
        Math.min(relativeStart, len);

      // Steps 9-10.
      var end = arguments[2];
      var relativeEnd = end === undefined ?
        len : end >> 0;

      // Step 11.
      var final = relativeEnd < 0 ?
        Math.max(len + relativeEnd, 0) :
        Math.min(relativeEnd, len);

      // Step 12.
      while (k < final) {
        O[k] = value;
        k++;
      }
      // Step 13.
      return O;
    }
  });
}

После четырех часов кодинга я не могу это кодировать ✍✍✍, посмотрите на чужой стандартный текст, отпустите меня😭


не изменяет исходный метод массива

slice

определение:

Возвращает новый объект массива, которыйbeginа такжеendОпределяется исходным массивоммелкая копия(включатьbegin, исключаяend). Исходный массив не будет изменен.

Для глубокого и мелкого копирования вы можете увидеть мою статьюКак написать удовлетворительный глубокий текст на собеседовании (подходит для младшего фронтенда)

грамматика:

arr.slice([begin[, end]])

параметр:

 begin (可选)
 1. 提取起始处的索引(从 0 开始),从该索引开始提取原数组元素。
 2. 如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取
 3. slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)
 4. 如果省略 begin,则 slice 从索引 0 开始。
 5. 如果 begin 大于原数组的长度,则会返回空数组。	
 
 end   (可选)
 1.	 slice(1,4) 会提取原数组中从第二个元素开始一直到第四个元素的所有元素 (索引为 1, 2, 3的元素)
 2. 如果该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取。
 3. 如果 end 被省略,则 slice 会一直提取到原数组末尾。
 4. 如果 end 大于数组的长度,slice 也会一直提取到原数组末尾。

Применение:

Возвращает часть существующего массива

var fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango'];
var citrus = fruits.slice(1, 3);

// fruits contains ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango']
// citrus contains ['Orange','Lemon']

Когда в массиве есть значение ссылочного типа, поверхностная копия является адресом ссылочного типа.

// 使用 slice 方法从 myCar 中创建一个 newCar。
var myHonda = { color: 'red', wheels: 4, engine: { cylinders: 4, size: 2.2 } };
var myCar = [myHonda, 2, "cherry condition", "purchased 1997"];
var newCar = myCar.slice(0, 2);
newCar[0].color = 'blue';
console.log(myHonda.color)  // bule

Массивоподобный объект преобразуется в массив

function list() {
  return Array.prototype.slice.call(arguments);
}

var list1 = list(1, 2, 3); // [1, 2, 3]
//你也可以简单的使用 [].slice.call(arguments) 来代替

Взгляните на array.js в исходном коде v8.Строка 762 начинает путешествие по слайсу

(function () {
  'use strict';
  var _slice = Array.prototype.slice;

  try {
    // Can't be used with DOM elements in IE < 9
    _slice.call(document.documentElement);
  } catch (e) { // Fails in IE < 9
    // This will work for genuine arrays, array-like objects, 
    // NamedNodeMap (attributes, entities, notations),
    // NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes),
    // and will not fail on other DOM objects (as do DOM elements in IE < 9)
    Array.prototype.slice = function(begin, end) {
      // IE < 9 gets unhappy with an undefined end argument
      end = (typeof end !== 'undefined') ? end : this.length;

      // For native Array objects, we use the native slice function
      if (Object.prototype.toString.call(this) === '[object Array]'){
        return _slice.call(this, begin, end); 
      }
      // For array like object we handle it ourselves.
      var i, cloned = [],
        size, len = this.length;
      // Handle negative value for "begin"
      var start = begin || 0;
      start = (start >= 0) ? start : Math.max(0, len + start);
      // Handle negative value for "end"
      var upTo = (typeof end == 'number') ? Math.min(end, len) : len;
      if (end < 0) {
        upTo = len + end;
      }
      // Actual expected size of the slice
      size = upTo - start;
      if (size > 0) {
        cloned = new Array(size);
        if (this.charAt) {
          for (i = 0; i < size; i++) {
            cloned[i] = this.charAt(start + i);
          }
        } else {
          for (i = 0; i < size; i++) {
            cloned[i] = this[start + i];
          }
        }
      }

      return cloned;
    };
  }
}());

Я думаю, что это больше процесс моделирования, и единственное, что немного сложно понять, это определение граничного значения, поэтому я нашел код под спецификацией, вы можете обратиться к нему.

С точки зрения кода нужно обратить внимание:

  • Если вы хотите его использовать, просто посмотрите главу о параметрах 🈯
  • Что касается проблемы глубокого и поверхностного копирования, если элемент является ссылкой на объект (а не фактическим объектом),sliceскопирует ссылку на объект в новый массив. Обе ссылки на объекты ссылаются на один и тот же объект. Если объект, на который делается ссылка, изменяется, этот элемент в новом и исходном массивах также изменяется.
  • Если в любой из двух массивов добавить новый элемент, это не повлияет на другой.
  • Для глубокого и поверхностного копирования вы можете прочитать эту статьюКак написать удовлетворительный глубокий текст на собеседовании (подходит для младшего фронтенда)

join

определение:

массив (илимассивоподобный объект) объединяет все элементы в строку и возвращает эту строку. Если в массиве только один элемент, то этот элемент возвращается без разделителя.

грамматика:

arr.join(separator)

параметр:

separator (可选)
指定一个字符串来分隔数组的每个元素。
如果需要,将分隔符转换为字符串。
如果缺省该值,数组元素用逗号(,)分隔。
如果separator是空字符串(""),则所有元素之间都没有任何字符。

Применение:

Объедините элементы массива, используя четыре разных разделителя

var a = ['Wind', 'Rain', 'Fire'];
var myVar1 = a.join();      // myVar1的值变为"Wind,Rain,Fire"
var myVar2 = a.join(', ');  // myVar2的值变为"Wind, Rain, Fire"
var myVar3 = a.join(' + '); // myVar3的值变为"Wind + Rain + Fire"
var myVar4 = a.join('');    // myVar4的值变为"WindRainFire"

объединять массивоподобные объекты

function f(a, b, c) {
  var s = Array.prototype.join.call(arguments);
  console.log(s); // '1,a,true'
}
f(1, 'a', true);

Взгляните на array.js в исходном коде v8.Строка 468 начинает путь соединения

Для обновления идея состоит в том, чтобы удалить каждый элемент массива или объекта, подобного массиву, и, наконец, завершить объединение строк с помощью разделителя.


toString

определение:

Возвращает строку, представляющую указанный массив и его элементы.

грамматика:

arr.toString()

Когда массив используется в качестве текстового значения или выполняется операция конкатенации строк, егоtoStringметод.

Применение:

const array1 = [1, 2, 'a', '1a'];
console.log(array1.toString());
// expected output: "1,2,a,1a"

concat

определение:

Используется для объединения двух или более массивов. Этот метод не изменяет существующий массив, а возвращает новый массив.

грамматика:

  var newArr =oldArray.concat(arrayX,arrayX,......,arrayX)

параметр:

arrayx(可选)
将数组和/或值连接成新数组。
如果省略了valueN参数参数,则concat会返回一个它所调用的已存在的数组的浅拷贝。

Применение:

Следующий код объединяет два массива в новый массив:

var alpha = ['a', 'b', 'c'];
var numeric = [1, 2, 3];

alpha.concat(numeric);
// result in ['a', 'b', 'c', 1, 2, 3]

объединить три массива

var num1 = [1, 2, 3],
    num2 = [4, 5, 6],
    num3 = [7, 8, 9];
var nums = num1.concat(num2, num3);
console.log(nums); 
// results in [1, 2, 3, 4, 5, 6, 7, 8, 9]

объединить значения в массив

var alpha = ['a', 'b', 'c'];

var alphaNumeric = alpha.concat(1, [2, 3]);

console.log(alphaNumeric); 
// results in ['a', 'b', 'c', 1, 2, 3]

Уведомление:

  • concatметод не меняетсяthisили любой массив, предоставленный в качестве аргумента, вместо этого возвращает поверхностную копию
  • concatСкопируйте ссылку на объект в новый массив. И исходный массив, и новый массив относятся к одному и тому же объекту. То есть, если указанный объект изменен, изменения видны как для нового массива, так и для исходного массива. Сюда входят элементы, которые также являются параметрами массива.
  • Массивы/значения сохраняются при конкатенации. Кроме того, любая операция над новым массивом (только если элемент не является ссылкой на объект) не влияет на исходный массив, и наоборот.

indexOf

определение:

Возвращает первый индекс в массиве, по которому можно найти данный элемент, или -1, если он не существует.

грамматика:

      array.indexOf(searchElement,fromIndex)

параметр:

searchElement  (必选)  要查找的元素
fromIndex 
1. 开始查找的位置。如果该索引值大于或等于数组长度,意味着不会在数组里查找,返回-1。
2. 如果参数中提供的索引值是一个负值,则将其作为数组末尾的一个抵消,即-1表示从最后一个元素开始查找
3.  注意:如果参数中提供的索引值是一个负值,并不改变其查找顺序,查找顺序仍然是从前向后查询数组。如果抵消后的索引值仍小于0,则整个数组都将会被查询。其默认值为0.
4. 采用的是严格等于 === 

Применение:

Метод indexOf определяет положение нескольких значений в массиве

var array = [2, 5, 9];
array.indexOf(2);     // 0
array.indexOf(7);     // -1
array.indexOf(9, 2);  // 2
array.indexOf(2, -1); // -1
array.indexOf(2, -3); // 0

Найти все вхождения указанного элемента

var indices = [];
var array = ['a', 'b', 'a', 'c', 'a', 'd'];
var element = 'a';
var idx = array.indexOf(element);
while (idx != -1) {
  indices.push(idx);
  idx = array.indexOf(element, idx + 1);
}
console.log(indices);
// [0, 2, 4]

indexOf() не распознаетNaN

		let a = ['啦啦', 2, 4, 24, NaN]
        console.log(a.indexOf('啦')); // -1 
        console.log(a.indexOf(NaN)); // -1 
        console.log(a.indexOf('啦啦')); // 0

Взгляните на array.js в исходном коде v8.Строка 1411 начинает путешествие indexOf.

if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function(searchElement, fromIndex) {

    var k;
    // 1. Let O be the result of calling ToObject passing
    //    the this value as the argument.
    if (this == null) {
      throw new TypeError('"this" is null or not defined');
    }

    var O = Object(this);

    // 2. Let lenValue be the result of calling the Get
    //    internal method of O with the argument "length".
    // 3. Let len be ToUint32(lenValue).
    var len = O.length >>> 0;

    // 4. If len is 0, return -1.
    if (len === 0) {
      return -1;
    }
    // 5. If argument fromIndex was passed let n be
    //    ToInteger(fromIndex); else let n be 0.
    var n = +fromIndex || 0;

    if (Math.abs(n) === Infinity) {
      n = 0;
    }
    // 6. If n >= len, return -1.
    if (n >= len) {
      return -1;
    }
    // 7. If n >= 0, then Let k be n.
    // 8. Else, n<0, Let k be len - abs(n).
    //    If k is less than 0, then let k be 0.
    k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
    // 9. Repeat, while k < len
    while (k < len) {
      if (k in O && O[k] === searchElement) {
        return k;
      }
      k++;
    }
    return -1;
  };
}

Это стандартный код, можете на него ссылаться, писать не буду, мне на свидание, времени нет 🙏

lastIndexOf

определение:

Возвращает индекс последнего указанного элемента (то есть допустимого значения или переменной JavaScript) в массиве или -1, если он не существует. Поиск вперед с конца массива, начиная сfromIndexначать с.

грамматика:

          arr.lastIndexOf(searchElement,fromIndex)

параметр:

searchElement  (必选)  要查找的元素
fromIndex 
1. 从此位置开始逆向查找
2. 默认为数组的长度减 1(arr.length - 1),即整个数组都被查找
3.  如果该值大于或等于数组的长度,则整个数组会被查找。如果为负值,将其视为从数组末尾向前的偏移
4. 即使该值为负,数组仍然会被从后向前查找。如果该值为负时,其绝对值大于数组长度,则方法返回 -1,即数组不会被查找。

Применение:

Индекс последнего вхождения этого элемента в массив или -1, если он не найден.

var array = [2, 5, 9, 2];
var index = array.lastIndexOf(2);
// index is 3
index = array.lastIndexOf(7);
// index is -1
index = array.lastIndexOf(2, 3);
// index is 3
index = array.lastIndexOf(2, 2);
// index is 0
index = array.lastIndexOf(2, -2);
// index is 0
index = array.lastIndexOf(2, -1);
// index is 3

Посмотрим как реализован последний indexOf🤳, времени нет.


Суммировать

Я хочу плакать, но нет слез🤥, мне понадобился день + код, чтобы завершить эти знания массива JS, и нашел"1,2 Вт слово"👍👍👍 Многие определения заимствованы с официального сайта, в основном из-за боязни ввести в заблуждение многих фронтенд-персонала, таких же элементарных, как я, поэтому используются стандартные термины официального сайта.

Если код сложный, я написал его сам и многому научился.

"Если вам это нравится, вы можете поставить лайк 👍👍👍 / подписаться, поддержать, я надеюсь, вы сможете прочитать эту статью и получить что-то"

Ссылаться на

MDN_Array

Китти-трюки с JS-массивом

Исходный код V8

Подробный обход JS

25 расширенных способов использования массива, которые вы должны знать

9 основных операций связанного списка "алгоритмы и структуры данных"