Skip to content

Instantly share code, notes, and snippets.

@dSalieri
Last active November 6, 2023 13:48
Show Gist options
  • Select an option

  • Save dSalieri/de31add7ffedded638a228f2933858d9 to your computer and use it in GitHub Desktop.

Select an option

Save dSalieri/de31add7ffedded638a228f2933858d9 to your computer and use it in GitHub Desktop.
Алгоритм SpeciesConstructor
/// Эта функция отсылка к спецификационному алгоритму https://tc39.es/ecma262/#sec-speciesconstructor
/// Смысл операции извлечь конструктор для переданного объекта
/*
Наверное вас смущает, что первая строчка кода могла бы решить этот вопрос,
но особенность в том что есть [Symbol.species], через который можно сообщить что использовать значение из
"constructor" вы не хотите, а хотите возспользоваться чем-то другим, решение - [Symbol.species]
*/
function SpeciesConstructor(O, defaultConstructor){
const C = Reflect.get(O, "constructor");
if(C === undefined) return defaultConstructor;
const isObject = (o) => typeof o === "object" && o !== null || typeof o === "function";
if(!isObject(C)) throw TypeError("C is not an Object");
const S = Reflect.get(C, Symbol.species);
if(S === undefined || S === null) return defaultConstructor;
const isConstructor = (c) => typeof c === "function" && Reflect.has(c.prototype ?? Object.create(null), "constructor");
if(isConstructor(S)) return S;
throw TypeError("S is not constructor");
}
/// примеры
SpeciesConstructor({}, Array); /// ƒ Array() { [native code] }
SpeciesConstructor(Promise.resolve(1), Array) /// ƒ Promise() { [native code] }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment