SOURCE

/**
 * Array()
 * JavaScript的 Array 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象
 * 数组是一种类列表对象,它的原型中提供了遍历和修改元素的相关操作。
 * JavaScript 数组的长度和元素类型都是非固定的。
 * 因为数组的长度可随时改变,并且其数据在内存中也可以不连续,
 * 所以 JavaScript 数组不一定是密集型的,这取决于它的使用方式。
 * => 一个数组
 */
const arr1 = Array(1, 2, 3, 4);
const arr2 = Array(8);
const arr3 = new Array(1, 2, 3, 4);
// console.log(arr1, arr2, arr3);

/**
 * Array.prototype[@@unscopables]
 * Symbol 属性 @@unscopable 包含了所有 ES2015 (ES6) 中新定义的、
 * 且并未被更早的 ECMAScript 标准收纳的属性名。这些属性被排除在由 with 语句绑定的环境中
 * with 绑定中未包含的数组默认属性有:
 * copyWithin()
 * entries()
 * fill()
 * find()
 * findIndex()
 * includes()
 * keys()
 * values()
 */
//array[Symbol.unscopables]
const arr4 = [1, 2, 3, 4];
// console.log(arr4[Symbol.unscopables]);

/**
 * length 是Array的实例属性。
 * 返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数,并且总是大于数组最高项的下标
 * length 属性的值是一个 0 到 2^32 - 1 的整数
 */
const arr5 = [1, 2, 3, , 4, , 5, 6];
// console.log(arr5.length);
arr5.length = 3;
// console.log(arr5);

/**
 * Array.prototype[@@iterator]()
 * @@iterator 属性和 Array.prototype.values() 属性的初始值是同一个函数对象
 * => iterator_obj
 */
//arr[Symbol.iterator]()
const arr6 = [1, 2, 3, 4, 5];
const forFn = (ger) => {
    for (let item of ger) {
        console.log(item);
    }
};
// forFn(arr6.values());
// forFn(arr6[Symbol.iterator]());
arr6[Symbol.iterator] = function () {
    const O = this;
    const len = O.length;
    let index = 0;

    const iterator = {
        next() {
            return index >= len ?
                { done: true } :
                {
                    value: [O[index], O[index++]],
                    done: false
                }
        }
    }


    return {
        [Symbol.iterator]: () => iterator,
        ...iterator,
    }
};
// forFn(arr6.values());
// forFn(arr6[Symbol.iterator]());
const obj1 = {
    name: 'obj1',
    age: 1
};
obj1[Symbol.iterator] = function () {
    const O = this;
    const kes = Object.keys(O);
    const len = kes.length;
    let index = 0;

    return {
        next() {
            return index >= len ? { done: true } : { value: kes[index++], done: false }
        }
    };
};
// forFn(obj1)

/**
 * get Array[@@species]
 * Array[@@species] 访问器属性返回 Array 的构造函数
 */
//Array[Symbol.species]
class MyArray extends Array {
    get [Symbol.species]() {
        return Array
    }
};

/**
 * Array.prototype.concat()
 * concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组
 * => new Array
 */
// new_array = old_array.concat(value1[, value2[, ...[, valueN]]])
const arr7 = [1, 2, 3, 4, 5];
const arr7Concat = [6, 7, 8];
// console.log(arr7.concat(arr7Concat), arr7, arr7Concat);
// arr7Concat[Symbol.isConcatSpreadable] = false;
// console.log(arr7.concat(arr7Concat), arr7, arr7Concat);

Array.prototype.myConcat = function (...args) {
    const O = this;
    const len1 = O.length;
    const result = [];

    const checkFn = (target) => {
        if (target[Symbol.isConcatSpreadable] === false) {
            result.push(target);
        } else {
            if (target.length && target[Symbol.isConcatSpreadable] !== false) {
                for (let i = 0; i < target.length; i++) {
                    result.push(target[i]);
                }
            }
        }
    }
    checkFn(O);
    for (let j = 0; j < args.length; j++) {
        checkFn(args[j]);
    }
    return result;
};
// console.log(arr7.myConcat(arr7Concat));
// arr7Concat[Symbol.isConcatSpreadable] = false;
// console.log(arr7.myConcat(arr7Concat));

/**
 * Array.prototype.copyWithin()
 * copyWithin() 方法浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度
 * target
 * 0 为基底的索引,复制序列到该位置。
 * 如果是负数,target 将从末尾开始计算。如果 target 大于等于 arr.length,将不会发生拷贝。
 * 如果 target 在 start 之后,复制的序列将被修改以符合 arr.length。
 * start
 * 0 为基底的索引,开始复制元素的起始位置。如果是负数,start 将从末尾开始计算。
 * 如果 start 被忽略,copyWithin 将会从0开始复制。
 * end
 * 0 为基底的索引,开始复制元素的结束位置。
 * copyWithin 将会拷贝到该位置,但不包括 end 这个位置的元素。
 * 如果是负数, end 将从末尾开始计算。如果 end 被忽略,
 * copyWithin 方法将会一直复制至数组结尾(默认为 arr.length)
 * => old_array
 */
//arr.copyWithin(target[, start[, end]])
const arr8 = [1, 2, 3, 4, 5];
// console.log(arr8.copyWithin(0,1,3));

/**
 * Array.prototype.entries()
 * entries() 方法返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对
 * => iterator_obj
 */
//arr.entries()
const arr9 = [[1, 34], [456, 2, 3, 44, 234], [4567, 1, 4, 5, 6], [34, 78, 23, 1]];
//二维数组排序
const sortFn1 = (arr) => {
    const len = arr.length;
    for (let i = 0; i < len; i++) {
        const item = arr[i];
        item.sort((a, b) => a - b);
    };

    return arr;
};
// console.log(sortFn1(arr9));
const sortFn2 = (arr) => {
    const entr = arr.entries();
    let finish = true
    while (finish) {
        const { value, done } = entr.next();
        if (done) {
            finish = false;
            break;
        }
        value[1].sort((a, b) => a - b);
    };
    return arr;
};
// console.log(sortFn2(arr9));

/**
 * Array.prototype.every()
 * every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值
 * 若收到一个空数组,此方法在一切情况下都会返回 true
 * => boolean
 */
//arr.every(callback(element[, index[, array]])[, thisArg])
const arr10 = [1, 2, 3, 4, 5];
const handle10Fn = function (item, index, thisArr) {
    return thisArr[index] + item + this[index] < 15;
};
const result = arr10.every(handle10Fn, arr10);
// console.log(result);

/**
 * Array.prototype.fill()
 * fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引
 * value
 * 用来填充数组元素的值。
 * start 可选
 * 起始索引,默认值为0。
 * end 可选
 * 终止索引,默认值为 this.length。
 * => old_array
 */
// arr.fill(value[, start[, end]])
const arr11 = [1, 2, , 3, 4, , 5, 6, , 8];
const fillFn = (arr) => {
    const len = arr.length;

    for (let i = 0; i < len; i++) {
        if (!arr[i]) {
            arr.fill(arr[i - 1] - 1, i, i + 1);
        }
    }

    return arr;
};
// console.log(fillFn(arr11));

/**
 * Array.prototype.filter()
 * filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
 * => new Array
 */
//newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
const arr12 = [1, , 2, , 3, , 4, , 5, , 6, , 7];
const handle12Fn = function (item, index, thisArr) {
    return thisArr[index] && this[index]
};
const arr12Filter = arr12.filter(handle12Fn, arr12);
// console.log(arr12Filter);

/**
 * Array.prototype.find()
 * find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined.
 * => item / undefined
 */
//arr.find(callback[, thisArg])
const arr13 = [1, 2, 3, 4, 5, 7, 8];
const hanlde13Fn = function (item, index, thisArr) {
    return this[index] + thisArr[index] === 16
}
const target13 = arr13.find(hanlde13Fn, arr13);
// console.log(target13);

/**
 * Array.prototype.findIndex()
 * findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1。
 * => index / -1
 */
// arr.findIndex(callback[, thisArg])
const arr14 = [1, 2, 3, 4, 5, 6];
const handle14Fn = function (item, index, thisArr) {
    return this[index] + thisArr[index] === 12
};
const target14 = arr14.findIndex(handle14Fn, arr14);
// console.log(target14);

/**
 * Array.prototype.flat()
 * flat() 方法会按照一个可指定的深度递归遍历数组,
 * 并将所有元素与遍历到的子数组中的元素合并为一个新数组返回
 * depth 可选 指定要提取嵌套数组的结构深度,默认值为 1。
 * => new Array
 */
//newArray = arr.flat([depth])
const arr15 = [[1, 2], [[3, 4]], 5];
const target15 = arr15.flat(2);
// console.log(target15);

/**
 * Array.prototype.flatMap()
 * flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。
 * 它与 map 连着深度值为1的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些
 * => new Array
 */
// new_array = arr.flatMap(function callback(currentValue[, index[, array]]) {
//     // return element for new_array
// }[, thisArg])
const arr16 = [[1, 2, 3], 5, [[6]], 7, [8, 9]];
const handle15Fn = function (item, index, thisArg) {
    return item;
}
const target16 = arr16.flatMap(handle15Fn);
// console.log(target16);

/**
 * Array.prototype.forEach()
 * forEach() 方法对数组的每个元素执行一次给定的函数。
 * => undefined
 */
//arr.forEach(callback(currentValue [, index [, array]])[, thisArg])
const arr17 = [1, 2, 3, 4, 5];
const handle17Fn = function (item, index, thisArr) {
    console.log(thisArr[index], item);
};
// const target17 = arr17.forEach(handle17Fn);
// console.log(target17);

/**
 * Array.from()
 * Array.from() 方法对一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。
 * => new Array
 */
//Array.from(arrayLike[, mapFn[, thisArg]])
const obj2 = {
    length: 3,
    0: 'age',
    2: 'name'
};
const handle18Fn = function (item, index) {
    console.log(item, index);
    if (item) {
        return item + 'yes';
    }
    return 100;
}
// const arr18 = Array.from(obj2, handle18Fn);
// console.log(arr18);

/**
 * Array.prototype.includes()
 * includes() 方法用来判断一个数组是否包含一个指定的值,
 * 根据情况,如果包含则返回 true,否则返回 false。
 * => boolean
 */
//arr.includes(valueToFind[, fromIndex])
const arr19 = [1, '2', 3, 4, '5'];
const target19 = arr19.includes('2', 2);
// console.log(target19);

/**
 * Array.prototype.indexOf()
 * indexOf()方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
 * => index / -1
 */
//arr.indexOf(searchElement[, fromIndex])
const arr20 = [1, 2, 3, 4, '5', 6, 7];
const target20 = arr19.indexOf('5', 5);
// console.log(target20);


/**
 * Array.isArray()
 * Array.isArray() 用于确定传递的值是否是一个 Array。
 * => boolean
 */
//Array.isArray(obj)
const arr21 = [[], {}, '', undefined, NaN, true];
// for (let item of arr21) {
//     console.log(Array.isArray(item));
// }

/**
 * Array.prototype.join()
 * join() 方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。
 * 如果数组只有一个项目,那么将返回该项目而不使用分隔符。
 * => string
 */
const arr22 = [1, 2, 3, 4];
const target22 = arr22.join('@');
// console.log(target22);

/**
 * Array.prototype.keys()
 * keys() 方法返回一个包含数组中每个索引键的Array Iterator对象。
 * arr.keys()
 * => iterator_obj
 */
const arr23 = [1, 2, 3, 4, 5];
const kes23 = arr23.keys();
// console.log(typeof kes23);
// for (let item of kes23) {
//     console.log(item);
// };


/**
 * Array.prototype.lastIndexOf()
 * lastIndexOf() 方法返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个的索引,
 * 如果不存在则返回 -1。从数组的后面向前查找,从 fromIndex 处开始。
 * => index / -1
 */
// arr.lastIndexOf(searchElement[, fromIndex])
const arr24 = [1, 2, '3', 4, 5, '6', '3'];
const target24 = arr24.lastIndexOf('3', -1);
// console.log(target24);


/**
 * Array.prototype.map()
 * map() 方法创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。
 * => new Array
 */
// new_array = arr.map(function callback(currentValue[, index[, array]]) {
//  // Return element for new_array 
// }[, thisArg])
const arr25 = [1, 2, 3, 4, 5];
const handle25Fn = function (item, index, thisArr) {
    return this[index] + thisArr[index];
};
const target25 = arr25.map(handle25Fn, arr25);
// console.log(target25);

/**
 * Array.of()
 * Array.of() 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。
 * Array.of() 和 Array 构造函数之间的区别在于处理整数参数:
 * Array.of(7) 创建一个具有单个元素 7 的数组,
 * 而 Array(7) 创建一个长度为7的空数组(注意:这是指一个有7个空位(empty)的数组,
 * 而不是由7个undefined组成的数组)。
 * => new Array
 */
//Array.of(element0[, element1[, ...[, elementN]]])
const arr26 = Array.of([1, 2, 3], 4, 5, 6);
// console.log(arr26);

/**
 * Array.prototype.pop()
 * pop()方法从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度。
 * arr.pop()
 * => popItem / undefined
 */
const arr27 = [1, 2, 3, 4, 5, [6, 7]];
const target27 = arr27.pop();
// console.log(target27, arr27);

/**
 * Array.prototype.push()
 * push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。
 * => newLength 
 */
//arr.push(element1, ..., elementN)
const arr28 = [1, 2, 3, 4, 5];
const target28 = arr28.push(6, 7, 8);
// console.log(target28, arr28);

/**
 * Array.prototype.reduce()
 * reduce() 方法对数组中的每个元素按序执行一个由您提供的 reducer 函数,
 * 每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。
 * 第一次执行回调函数时,不存在“上一次的计算结果”。如果需要回调函数从数组索引为 0 的元素开始执行,
 * 则需要传递初始值。
 * 否则,数组索引为 0 的元素将被作为初始值 initialValue,
 * 迭代器将从第二个元素开始执行(索引为 1 而不是 0)。
 * => acc
 */
const arr29 = [1, 2, 3, 4, 5];
const handle29Fn = function (acc, item, index, thisArr) {
    acc.push(thisArr[index] * 10);
    return acc;
}
const target29 = arr29.reduce(handle29Fn, []);
// console.log(target29);

/**
 * Array.prototype.reduceRight()
 * reduceRight() 方法接受一个函数作为累加器(accumulator)和
 * 数组的每个值(从右到左)将其减少为单个值。
 */
// arr.reduceRight(callback(accumulator, currentValue[, index[, array]])[, initialValue])
const arr30 = [1, 2, 3, 4, 5];
const handle30Fn = function (acc, item, index, thisArr) {
    acc.push(thisArr[index] * 10);
    return acc;
};
const target30 = arr30.reduceRight(handle30Fn, []);
// console.log(target30);

/**
 * Array.prototype.reverse()
 * reverse() 方法将数组中元素的位置颠倒,并返回该数组。
 * 数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。
 * => old_Array
 */
//arr.reverse()
const arr31 = [1, 2, 3, 4, 5, 6];
const target31 = arr31.reverse();
// console.log(target31, arr31);

/**
 * Array.prototype.shift()
 * shift() 方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
 * => item / undefined
 */
const arr32 = [, 1, 2, 3, 4, 5];
const target32 = arr32.shift();
// console.log(target32, arr32);

/**
 * Array.prototype.slice() 
 * slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。
 * 原始数组不会被改变。
 * begin 可选
 * 提取起始处的索引(从 0 开始),从该索引开始提取原数组元素。
 * 如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,
 * slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。
 * 如果省略 begin,则 slice 从索引 0 开始。如果 begin 超出原数组的索引范围,则会返回空数组。
 * end 可选
 * 提取终止处的索引(从 0 开始),在该索引处结束提取原数组元素。
 * slice 会提取原数组中索引从 begin 到 end 的所有元素(包含 begin,但不包含 end)。
 * slice(1,4) 会提取原数组中从第二个元素开始一直到第四个元素的所有元素 (索引为 1, 2, 3的元素)。
 * 如果该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取。 
 * slice(-2,-1) 表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,
 * 也就是只有倒数第二个元素)。
 * 如果 end 被省略,则 slice 会一直提取到原数组末尾。
 * 如果 end 大于数组的长度,slice 也会一直提取到原数组末尾。
 * => new Array
 */
//arr.slice([begin[, end]])
const arr33 = [1, 2, 3, 4, 5, 6];
const target33 = arr33.slice(0, 3);
// console.log(target33, arr33);

/**
 * Array.prototype.some()
 * some() 方法测试数组中是不是至少有1个元素通过了被提供的函数测试。
 * => boolean
 */
// arr.some(callback(element[, index[, array]])[, thisArg])
const arr34 = [1, 2, 3, 4, 5];
const handle34Fn = function (item, index, thisArr) {
    return thisArr[index] + item + this[index] === 15;
};
const target34 = arr34.some(handle34Fn, arr34);
// console.log(target34);

/**
 * Array.prototype.sort()
 * sort() 方法用原地算法对数组的元素进行排序,并返回数组。
 * 默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的
 * 由于它取决于具体实现,因此无法保证排序的时间和空间复杂性。
 * compareFunction 可选
 * 用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序。
 * firstEl
 * 第一个用于比较的元素。
 * secondE
 * 第二个用于比较的元素。
 * => old_array
 */
//arr.sort([compareFunction])
const arr35 = [1, 2, 3, 4, 5, 6, 7];
const handle35Fn = function (first, second) {
    return second - first;
};
const target35 = arr35.sort(handle35Fn);
// console.log(target35);

/**
 * Array.prototype.splice()
 * splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。
 * 此方法会改变原数组。
 * 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() 将只删除数组元素。
 * => new Array
 */
//array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
const arr36 = [1, 2, 3, 3, 5, 6];
const target36 = arr36.splice(3, 1, 4);
// console.log(target36, arr36);

/**
 * Array.prototype.toLocaleString()
 * toLocaleString() 返回一个字符串表示数组中的元素。
 * 数组中的元素将使用各自的 toLocaleString 方法转成字符串,
 * 这些字符串将使用一个特定语言环境的字符串(例如一个逗号 ",")隔开。
 * locales 可选
 * 带有BCP 47语言标记的字符串或字符串数组,关于locales参数的形式与解释,请看Intl页面。
 * options 可选
 * 一个可配置属性的对象,对于数字 Number.prototype.toLocaleString(),
 * 对于日期Date.prototype.toLocaleString().
 * => string
 */
//arr.toLocaleString([locales[,options]]);
const arr37 = [1, 2, 3, 4, 5, 6];
const target37 = arr37.toLocaleString();
// console.log(target37, arr37);

/**
 * Array.prototype.toString()
 * toString() 返回一个字符串,表示指定的数组及其元素。
 * => string
 */
const arr38 = [1, 2, 3, , , 6];
const target38 = arr38.toString();
// console.log(target38);

/**
 * Array.prototype.unshift()
 * unshift() 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)。
 * => newLength
 */
// arr.unshift(element1, ..., elementN)
const arr39 = [1, 2, 3, 4, 5, 6];
const target39 = arr39.unshift(0, 1);
// console.log(target39, arr39);

/**
 * Array.prototype.values()
 * values() 方法返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值
 * => iterator_obj
 */
// arr.values()
const arr40 = [1, 2, 3, 4, 4, 5];
const vals40 = arr40.values();
// for (let item of vals40) {
//     console.log(item);
// }










console 命令行工具 X clear

                    
>
console