wywołanie obj.div.p("text") (js)

0

Witam, mam zadanie stworzyć obj który po wywołaniu:
1 obj.div("text") zwraca

<div>text</div>

2 1 obj.p("text") zwraca

<p>text</p>

i to wiem jak zrobić ale trzecie wywołanie sprawia mi problem, jeśli można proszę o podpowiedź jak do tego podejść?
3 obj.div.p("text") zwraca

<div><p>text</p></div>
0

Pokaż, co tam już masz, bo na podstawie samego opisu, nie mam pewności, czego konkretnie oczekujesz.

0

Ma się tak zachowywać ale nie ma być wywoływane el.div(el.p("bbb")) tylko przez el.div.p("bbb")

function Element(){
  this.text="text";
}

Element.prototype.div = function(newText){
  this.text="<div>"+newText+"</div>";
  return this.text;
};
Element.prototype.p = function(newText){
  this.text="<p>"+newText+"</p>";
  return this.text
};

const el = new Element();
console.log(el.div(el.p("bbb")));

Dodam że powinna być tez możliwość wywołania el.div("bbb") i zwróci

<div>bbb</div>
0

Nie znam się na pisaniu obiektowym, ale coś takiego?


function Element(){
  this.text="text";
}

function subElement(){
  this.text="text";
}


Element.prototype.div = function(newText){
  this.text="<div>"+newText+"</div>";
  return this.text;
};
Element.prototype.p = function(newText){
  this.text="<p>"+newText+"</p>";
  return this.text
};



subElement.prototype.p = function(newText){
  this.text="<div><p>"+newText+"</p></div>";
  return this.text
};

const el = new Element();

Element.prototype.div2 = new subElement();

console.log(el.div(el.p("bbb")));
console.log(el.div2.p("aaa"));

Może ktoś to polepszy?

0

@Freja Draco: Ale jak wywołam już console.log(el.div2("aaa")); to nie działa a ma działać dla wersji console.log(el.div2("aaa")); oraz console.log(el.div2.p("aaa")) tu jest problem :( Generalnie podałem skróconą wersję w całości ma być możliwość dla div p i span i ma być możliwość wywołania el.div el.div.p el.div.p.span el.spam el.p el.p.span ogólnie w różnych konfiguracjach :)

0

Trochę haxy

Element.prototype.div.p = function(newText){
  var self = Element.prototype;
  return self.div(self.p(newText));
};
1

Trochę napisałem, ale żeby nie było za łatwo to nie działa (nie wiem czemu, nigdy nie używałem Proxy ale wygląda to jak coś czego potrzebujesz):

class HTMLBuilder {
    constructor() {
        this.elements = ['div', 'p'];
        this.chain = [];
        return new Proxy(this, {
            get: function(builder, field) {
                if (builder.elements.includes(field)) {
                  builder.chain.push(field);
                  return builder;
                }
               
                return function (text) {
                    console.log(chain, text);
                    return 'todo';
                }
            }
        });
    }
}

const builder = new HTMLBuilder();

builder.div.p('text')
0

@szatkus:

 const obj = {
  p: text => `<p>${text}</p>`,
  div: text => `<div>${text}</div>`
};
obj.div.p = text => obj.div(obj.p(text));
obj.p.div = text => obj.p(obj.div(text));

console.log(obj.div("aaa"));
console.log(obj.div.p("aaa"));
console.log(obj.p.div("aaa"));

Działa cos z tym pokombinuję i może będzie ok :)

0

@szatkus: Z tego co mi zadający zadanie powiedział bardziej to ma się opierać na kompozycjach i dziedziczeniu.

0

no to w takim razie opierając rozwiązanie o kompozycje funkcji można coś takiego zrobić:

function el(contents, parents = []) {
	const makeEl = type => contents => 
          el(contents, parents.concat(contents => `<${type}>${contents}</${type}>`));

	if (!contents) return {
		div: makeEl('div'),
		span: makeEl('span'),
	};
	return parents.reduceRight((acc, f) => f(acc), contents);
}

console.log(el().div().div().span("kociak"));

z tym, że zamiast:
el.div.div.span("kociak")
musiałbyś dodać nawiasy:
el().div().div().span("kociak")

Ale równie dobrze można do tego dodać ES6 Proxy (ew. gettery z ES5), żeby wyłapywać moment, kiedy użytkownik pisze el.div i przerabia to na wywołanie funkcji, ale to tylko cukier składniowy...

Co do dziedziczenia, to nie wiem, co ma do tego dziedziczenie? Chociaż czy kompozycja funkcji nie jest w pewnym sensie dziedziczeniem? Ja tam się nie znam na tych paradygmatach. Chyba nie poradziłbym sobie ani na studiach informatycznych ani w technikum, ani gdziekolwiek indziej, gdzie każą robić zadania pod linijkę...

0

@LukeJL: Ma być na kompozycjach i wywołanie z kropką, dzięki ogólnie wszystkim za przykłady popatrzę na wasze rozwiązania i może coś z tego uda się zrobić

0

No to jak z kropką, to Proxy.

BTW kto dał ci takie zadanie? Bo tego typu wytyczne ma się opierać na kompozycjach i dziedziczeniu. są dość nierozsądne. To ty powinieneś wiedzieć, jak to zaimplementować, bo od tego jest programista, żeby dokonywać wyboru, a nie gostek, który palcem nie ruszy, tylko mówi, że ma być tak i tak, mimo, że lepsza implementacja może być zupełnie inna niż się komuś na górze wydaje.

Wymaganie co do kropki z kolei jest już bardziej sensowne, bo to wymóg konkretnego kształtu API. Z drugiej strony też należałoby się zastanowić, czy API w stylu el.div.div.span("test") jest sensowne. Co jeśli będziesz chciał mieć dwa elementy span w divie?

<div>
   <span>abc</span>
   <span>def</span>
</div>

jak to zrobisz za pomocą samych kropek, jeśli ta notacja zakłada jak rozumiem, że tylko jeden element potomny może istnieć w danym elemencie? Jeśli div.div.span("abc") zwraca już stringa, to nie zrobisz div.div.span("abc").span("def"), zresztą to by nie było logiczne, skoro notacja jest taka, że po kropce masz wejście do elementu potomnego, a chcesz uzyskać rodzeństwo.
Chyba, żeby zmodyfikować API, żeby przyjmował tablice:
div.div([span("abc"), span("def")])
Ale jak iść dalej, to po co w ogóle jakieś kropki, bardziej praktyczniej byłoby zrobić API mniej więcej takie:

const html = div(
   div(
       span("abc"),
       span("def"),
   )
)

Oczywiście wiem, że takie masz wytyczne, ale cóż, miej świadomość, że ten, kto to zlecał, nie przemyślał tego dobrze. Aha i bycie jakimś nauczycielem czy wykładowcą go nie tłumaczy, bo tym bardziej powinien uczyć praktycznego podejścia, a nie uwsteczniać swoich uczniów przez dawanie z d... wymagań. Z drugiej strony samo zadanie (pomijając narzucony z d**y sposób implementacji) jest ciekawe. Zrobiłem je w JS, a potem próbowałem odtworzyć rozwiązanie w Rust, którego teraz się uczę.

1 użytkowników online, w tym zalogowanych: 0, gości: 1