Skip to content

Latest commit

 

History

History
128 lines (106 loc) · 7.37 KB

Array.from - Converting Pseudo Arrays and Iterables in JavaScript.hy.md

File metadata and controls

128 lines (106 loc) · 7.37 KB

Ինչպե՞ս փսևդոզանգվածներից և իտերացվող օբյեկտներից ստանալ զանգված՝ օգտվելով ES6 ստանդարտում ներդրված Array.from մեթոդից:

Array.from մեթոդը փսևդոզանգվածներից (երբեմն անվանում են նաև զանգվածանման օբյեկտներ) և իտերացվող օբյեկտներից ստեղծում և վերադարձնում է զանգված։ Նախ հասկանանք թե ինչ են իրենցից ներկայացնում փսևդոզանգվածները և իտերացվող օբյեկտները։

Փսևդոզանգվածները կամ ինչպես երբեմն ընդունված է անվանել զանգվածանման օբյեկտները դրանք սովորական օբյեկտներ են, որոնց հատկությունների անունները (բանալիները) իրենցից ներկայացնում են String տիպի արժեքներ, որոնք սակայն հեշտությամբ կարող են վերափոխվել ամբողջ թվերի՝ այսպիսով հիշեցնելով զանգվածների ինդեքսները։ Նրանք նաև ունեն length հատկություն, որը ցույց է տալիս օբյեկտում առկա հատկությունների քանակը։

Փսևդոզանգվածի դասական օրինակ է ֆունկցիաների ներսում հասանելի, և իր մեջ ֆունկցիային հաղորդված բոլոր արգումենտները կրող arguments-ը։ Այդ փսևդոզանգվածի մասին առավել մանրամասն կարող եք ծանոթանալ այստեղ։

Իտերացվող օբյեկտները պետք է պարտադիր ունենան [Symbol.iterator] հատկությունը, որը սահմանում և ապահովում է օբյեկտի իտերացիայի ճշգրիտ հերթականությունն ու անխափան աշխատանքը։ Եթե ավելի պարզ՝ բոլոր այն օբյեկտները, որոնց վրա հնարավոր է կանչել for of ցիկլը, հանդիսանում են իտերացվող օբյեկտներ։ Օրինակ Map-ն ու Set-ն իտերացվող օբյեկտներ են։

Փսևդոզանգվածներից կամ իտերացվող օբյեկտներից զանգված ստանալու համար մենք նրանց որպես արգումենտ տալիս ենք Array կոնստրուկտորի from ստատիկ մեթոդին։ Օրինակ փորձենք Array.from մեթոդին որպես արգումենտ տալ Map օբյեկտ.

const person = new Map();
person.set("name", "John");
person.set("age", 25);

console.log(person); // {"name" => "John", "age" => 25}

const arrFromMap = Array.from(person);
console.log(arrFromMap); // [["name", "John"], ["age", 25]]

Set-ը նույնպես կարող է օգտագործվել.

const fruits = new Set();
fruits.add("apple");
fruits.add("oranges");

console.log(fruits); // {"apple", "oranges"}

const arrFromSet = Array.from(fruits);
console.log(arrFromSet); // ["apple", "oranges"]

Մենք կարող ենք այս մեթոդի օգնությամբ զանգված ստանալ նաև arguments փսևդոզանգվածից.

function foo() {
  return Array.from(arguments);
}

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

Այս մեթոդով կարելի է զանգված ստանալ անգամ String տիպին պատկանող արժեքներից՝

const arrFromString = Array.from("hello");
console.log(arrFromString); // ["h", "e", "l", "l", "o"]

Հետաքրքիր է, որ Array.from մեթոդն ունի նաև երկու ոչ պարտադիր պարամետրներ, մեթոդի լիարժեք սինթաքսն ունի հետևյալ տեսքը՝

  • Array.from(object, mapFunction, thisValue);

  • object պարամետրին արդեն ծանոթ ենք, այն պարտադիր է և պետք է լինի փսևդոզանգված կամ իտերացվող օբյեկտ։

  • mapFunction-ը հետադարձ կանչի (callback) ֆունկցիա է, որը կանչվում է զանգվածի յուրաքանչյուր էլեմենտի համար (ինչպես արդեն ասվեց, այս պարամետրը պարտադիր չէ): Այն իր գործառույթով նման է զանգվածների map մեթոդին, և Array.from(obj, mapFn, thisArg) կանչը համարժեք է Array.from(obj).map(mapFn, thisArg) կանչին, միայն այն տարբերությամբ, որ միջանկյալ զանգված այլևս չի ստեղծվում։

  • thisValue-ն սահմանում է this-ի արժեքը՝ mapFunction-ի կանչի համար (նույնպես հանդիսանում է ոչ պարտադիր պարամետր):

Մեթոդը ECMAScript ստանդարտում ներդրվել է 2015 թվականին (ES6) և գործնականում աջակցվում է բոլոր ժամանակակից ցանցային դիտարկիչների կողմից: Խնդիրներ կարող են առաջանալ համեմատաբար հին Internet Explorer դիտարկիչի վրա (IE վերջին 11-րդ տարբերակը նույնպես այս մեթոդը չի ճանաչում և ապահովության համար կարելի է սքրիփթի մեջ ավելացնել մեթոդի պոլիֆիլը): Պոլիֆիլի օրինակ՝

if (!Array.from) {
  Array.from = (function () {
    var toStr = Object.prototype.toString;
    var isCallable = function (fn) {
      return typeof fn === "function" || toStr.call(fn) === "[object Function]";
    };
    var toInteger = function (value) {
      var number = Number(value);
      if (isNaN(number)) {
        return 0;
      }
      if (number === 0 || !isFinite(number)) {
        return number;
      }
      return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
    };
    var maxSafeInteger = Math.pow(2, 53) - 1;
    var toLength = function (value) {
      var len = toInteger(value);
      return Math.min(Math.max(len, 0), maxSafeInteger);
    };
    return function from(arrayLike /*, mapFn, thisArg */) {
      var C = this;
      var items = Object(arrayLike);
      if (arrayLike == null) {
        throw new TypeError(
          "Array.from requires an array-like object - not null or undefined"
        );
      }
      var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
      var T;
      if (typeof mapFn !== "undefined") {
        if (!isCallable(mapFn)) {
          throw new TypeError(
            "Array.from: when provided, the second argument must be a function"
          );
        }
        if (arguments.length > 2) {
          T = arguments[2];
        }
      }
      var len = toLength(items.length);
      var A = isCallable(C) ? Object(new C(len)) : new Array(len);
      var k = 0;
      var kValue;
      while (k < len) {
        kValue = items[k];
        if (mapFn) {
          A[k] =
            typeof T === "undefined"
              ? mapFn(kValue, k)
              : mapFn.call(T, kValue, k);
        } else {
          A[k] = kValue;
        }
        k += 1;
      }
      A.length = len;
      return A;
    };
  })();
}