2016-04-16 12 views
5

Powiedzmy, że mam funkcję komponowania obiektu z innych obiektów i przekazuję argumenty do funkcji - początkowo literał obiektu, a następnie obiekty, które chcę skomponować, aby rozszerzyć obiekt:Przesyłanie argumentów funkcji do Object.assign

composeFunc({}, obj1, obj2, obj3); 

liczba args przekazywane jest opcjonalna, jak mogę następnie przekazać args do Object.assign() zaczynając od 2 arg. Tak więc funkcja będzie wyglądać następująco:

function composeObj(objs) { 
    return Object.assign(arguments[1], arguments[2], arguments[3]... etc); 
} 

Z góry dzięki :)

+0

Już przekazałeś argument od 2. jako 'arguments' jest tablicą argumentów przekazanych do funkcji; – itzmukeshy7

+1

@ itzmukeshy7: To nie jest tablica, tylko tablicowa (co jest istotne dla pytania). Ale myślę, że ten przykład miał pokazać tylko to, co chcieli zrobić. Problem polega na tym, że liczba argumentów jest zmienna. –

+0

@ le-moi 'arguments' jest specjalną tablicą zawierającą wszystkie przekazane argumenty; – itzmukeshy7

Odpowiedz

5

Jeśli używasz ES2015 raczej niż tylko podkładki , można użyć spread notacji Array.from i slice:

function composeObj(objs) { 
    return Object.assign(...Array.from(arguments).slice(1)); 
} 

Albo po prostu za pomocą slice bezpośrednio zamiast po Array.from:

function composeObj(objs) { 
    return Object.assign(...Array.prototype.slice.call(arguments, 1)); 
} 

... zobacz Thomas' answer używając argumentów spoczynkowych, ponieważ jest to właściwy sposób w ES2015.

Jeśli nie używasz ES2015, można zrobić to samo z zaledwie podkładano Object.assign poprzez apply:

function composeObj(objs) { 
    return Object.assign.apply(Object, Array.prototype.slice.call(arguments, 1)); 
} 

tam, używamy Function#apply zamiast operatora spread (od ES5 i wcześniej nie ma operatora rozprzestrzeniania). Function#apply dzwoni do funkcji, którą wywołujesz, używając pierwszego argumentu jako this podczas wywołania, a używając tablicy (lub czegoś podobnego do tablicy) podajesz ją jako drugi argument jako argumenty dla wywołania.

Więc trzeba powiedzieć:

obj.foo(1, 2, 3); 

Ekwiwalent za pomocą Function#apply jest:

obj.foo.apply(obj, [1, 2, 3]); 

Pierwszy argument, obj opowiada apply co do wykorzystania jako this podczas rozmowy. Drugi argument to tablica argumentów do użycia.

Ale jeśli używasz operatora rozprzestrzeniania, nie ma potrzeby, rozdziela swój operand tablicy na dyskretne argumenty.

+0

Bingo, dziękuję TJ. Czy możesz mi powiedzieć, co się dzieje, jeśli nie masz nic przeciwko? Dlaczego nazywamy zastosowanie w Object.assign()? Również dlaczego Object jest pierwszym argumentem do zastosowania? Próba sprawdzenia w mojej głowie, co się dzieje - czy aplikacja służy do obsługi zwróconych argumentów, ponieważ są one konwertowane na macierz? –

+0

@LeMoi: Dodałem do końca, aby to wyjaśnić, ale jeśli używasz operatora rozprzestrzeniania z ES2015, nie musisz używać 'apply'. –

+0

Wielkie dzięki, to genialne :) –

2

ES2015:

function composeObj(objs, ...rest){ 
    return Object.assign(...rest); 
} 

rest będzie prawdziwa tablica wszystkie argumenty, począwszy od drugiego.

A Babel-output:

function composeObj(objs) { 
    for (var _len = arguments.length, rest = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 
    rest[_key - 1] = arguments[_key]; 
    } 

    return Object.assign.apply(Object, rest); 
} 

Wydaje się to być narzędzie, funkcja, która może być stosowana w każdym miejscu. Po przejściu arguments do innej funkcji, takiej jak Array.prototype.slice() lub Array.from(), composeObj nie zostanie zoptymalizowane przez kompilator JS. Więc nie rób tego.

Wszystko inne zostało już powiedziane w T.J. Crowders Odpowiedź i komentarze; tylko pokazując lepszą implementację.

+0

Jeśli OP używa ES2015, powinna to być zaakceptowana odpowiedź, a każdy, kto używa ES2015 z podobnym problemem, powinien postępować zgodnie z tą radą. (Gdzie była moja głowa?) –

Powiązane problemy