JavaScript lernen, aber wie?

CrownToFish

Neues Mitglied
Hallo zusammen,

ich möchte die Gelegenheit nutzen, mich hier kurz vorzustellen: Mein Name ist Micha, und ich habe eine Leidenschaft für die PC-Bastelei und Spieleentwicklung. Aktuell arbeitete viel mit der Unreal Engine und aktuell mit dem RPG Maker MZ.

Schon seit längerem hege ich den Traum, das Programmieren zu erlernen, doch bisher schreckten mich die vermeintlichen Schwierigkeiten und die Annahme ab, man müsse dafür studiert haben. Nun, kurz vor meinem 30. Geburtstag, habe ich den Schritt gewagt und mich mit KI-Unterstützung und vorgefertigten Skripten an umfassendere Programmierprojekte herangetraut. So ist es mir gelungen, ein komplexes Plugin für den RPG Maker MZ zu entwickeln, auch wenn mein Verständnis für die zugrundeliegenden Codes noch ausbaufähig ist bzw. fast nicht existent.

Hierbei wende ich mich an euch:

Meine Erfahrungen beschränken sich bislang auf Basiskenntnisse in verschiedenen Sprachen wie Python, JavaScript und C++. Im Zuge meines aktuellen Projekts habe ich mich für JavaScript entschieden, eine Sprache, die anscheinend leicht zu erlernen, aber schwer zu meistern ist.

Kürzlich stieß ich auf ein Beratungsangebot zur Erlernung von HTML, CSS und JavaScript in einem 9-monatigen Kurs, der auf einen Quereinstieg abzielt. Die Webseite und der YouTube-Kanal des Anbieters, Frederik Diekmann, sind hier zu finden:

Falls jemand Erfahrungen mit diesem Angebot hat, würde ich mich über Feedback freuen, insbesondere hinsichtlich der Seriosität und des Preis-Leistungs-Verhältnisses.

Nun zu meinen Fragen rund um das Erlernen von JavaScript:

  1. Ist JavaScript eine empfehlenswerte Sprache für Anfänger?
  2. Welche Herangehensweise würdet ihr empfehlen?
  3. Ist es ratsam, sich das Programmieren selbst beizubringen, oder besteht die Gefahr, sich schlechte Praktiken anzueignen?
  4. Könnt ihr Lernmaterialien wie Bücher, Websites oder Onlinekurse empfehlen?
Für jede Unterstützung und Empfehlung bin ich sehr dankbar.

Zu guter Letzt möchte ich noch mein aktuelles Projekt vorstellen, ein Plugin für den RPG Maker, das ich mit Hilfe von ChatGPT entwickelt habe. Der Code mag noch nicht perfekt sein, aber ich bin stolz auf das Erreichte. Einen Einblick in die Funktionsweise des Plugins bietet dieses Video:

Hier das Script dazu. Steinigt mich nicht für diese Unordnung. Schwer den Code zu pflegen oder gut zu strukturieren, wenn man die Sprache nicht versteht. Dennoch habe ich richtig Spaß bei diesem Projekt.

CrownRPGAttribute:
/*:
 * @plugindesc CrownRPGAttributes - Ein umfassendes Attributpunkt-Management-Plugin für den RPG Maker MZ.
 * @author CrownToFish
 *
 * @help
 * Das CrownRPGAttribute System ermöglicht es Spielern, Attributpunkte zu
 * verwalten und zu verteilen.
 * Spieler erhalten bei Spielbeginn und bei jedem Levelaufstieg
 * Attributpunkte.
 *
 * Außerdem bietet es eine breite Palette an weiteren Funktionen die nützlich
 * sind und es wird noch mehr dazu kommen.
 *
 * Plugin-Befehle:
 *   DistributePoints - Verteilt angegebene Punkte auf ein Attribut. Zum
 * Beispiel können so festgelegte NPCs dem Spieler etwas beibringen sofern
 * er genug verfügbare Punkte besitzt.
 *
 * Attribut-Struktur:
 *   Du kannst sämtliche Parameter selber festlegen. Darunter eine eigene
 * Variable setzen um die aktuellen Punkte des jeweiligen Attributs zu
 * speichern und überall abzurufen und zu nutzen. Zum Beispiel kannst du
 * Dialogen so mehr Tiefe geben und die Handlung beeinflussen.
 *
 * ACHTUNG: Das Plugin bietet derzeit keine Funktion Spielerstats zu
 * beeinflussen. Es wird aber als optionale Funktion nachgereicht.
 *
 * @param Attributes
 * @type struct<Attribute>[]
 * @desc Passe die Attribute an.
 *
 * @param StartPoints
 * @text Startpunkte
 * @type number
 * @desc Die verfügbaren Attributpunkte bei einem neuen Spielstart.
 * @default 0
 *
 * @param MaxPoints
 * @text Maximale Punkte
 * @type number
 * @desc Die maximale Anzahl an Punkten, die ein Spieler im Spielverlauf erhalten kann.
 * @default 50
 *
 * @param PointsPerLevel
 * @text Punkte pro Levelaufstieg
 * @type number
 * @desc Die Anzahl der Punkte, die ein Spieler pro Levelaufstieg erhält.
 * @default 1
 *
 * @command DistributePoints
 * @text Punkte verteilen
 * @desc Erstelle einen PC und lass ihn dem Spielcharakter etwas beibringen.
 *
 * @arg AttributeName
 * @text Attributname
 * @desc Der Name des Attributs, auf das die Punkte verteilt werden sollen.
 * @type text
 *
 * @arg Points
 * @text Punkte
 * @desc Anzahl der Punkte, die auf das Attribut verteilt werden sollen.
 * @type number
 * @min 1
 *
 * @param SuccessSound
 * @text Erfolgs-Sound
 * @type file
 * @dir audio/se/
 * @desc Der Sound, der abgespielt wird, wenn ein Punkt erfolgreich verteilt wird.
 *
 * @param FailureSound
 * @text Fehlschlag-Sound
 * @type file
 * @dir audio/se/
 * @desc Der Sound, der abgespielt wird, wenn ein Punkt nicht verteilt werden kann.
 *
 * @param SuccessMessage
 * @text Erfolgsmeldung
 * @desc Die Meldung, die angezeigt wird, wenn Punkte erfolgreich verteilt werden. Verwende {attribute}, {points} und {totalPoints} um weitere Informationen im Text anzuzeigen.
 * @type text
 * @default {attribute} wurde um {points} erhöht. Du hast jetzt {totalPoints} Punkte.
 *
 * @param FailureMessage
 * @text Fehlermeldung
 * @desc Die Meldung, die angezeigt wird, wenn die Verteilung eines Punktes fehlschlägt.
 * @default Punktverteilung auf {attribute} fehlgeschlagen!
 *
 *  * @param NPCs
 * @type struct<NPC>[]
 * @desc Definiere die NPCs, die im Spiel verwendet werden.
 * @default []
 *
 * @command DiscoverNPC
 * @text NPC entdecken
 * @desc Markiert einen NPC als entdeckt.
 *
 * @arg NPCName
 * @text NPC Name
 * @desc Der Name des NPCs, der als entdeckt markiert werden soll.
 * @type text
 *
 */

/*~struct~NPC:
 * @param Name
 * @desc Der Name des NPCs.
 * @type text
 *
 * @param Ort
 * @desc Der Ort, an dem der NPC gefunden werden kann.
 * @type text
 *
 * @param Attribut
 * @desc Das Attribut, das durch den NPC beeinflusst wird.
 * @type text
 *
 * @param Beschreibung
 * @desc Eine kurze Beschreibung des NPCs.
 * @type note
 *
 * @param BildEntdeckt
 * @desc Das Bild des NPCs, wenn er entdeckt wurde.
 * @type file
 * @dir img/pictures/
 *
 * @param BildVerdeckt
 * @desc Das Bild des NPCs, wenn er noch nicht entdeckt wurde.
 * @type file
 * @dir img/pictures/
 *
 * @param BildNormal
 * @desc Das Hintergrundbild für den normalen Zustand des Buttons.
 * @type file
 * @dir img/pictures/
 *
 * @param BildHovered
 * @desc Das Hintergrundbild für den hervorgehobenen Zustand des Buttons.
 * @type file
 * @dir img/pictures/
 *
 */

/*~struct~Attribute:
 * @param Name
 * @desc Der Name des Attributs.
 * @type string
 *
 * @param Description
 * @desc Die Beschreibung des Attributs.
 * @type string
 *
 * @param MaxPoints
 * @desc Die maximal verteilbaren Punkte für dieses Attribut.
 * @type number
 *
 * @param VariableId
 * @desc Die ID der RPG Maker Variable, in der der aktuelle Wert des Attributs gespeichert wird.
 * @type variable
 */

(function () {
    const pluginName = 'CrownRPGAttributes';
    const parameters = PluginManager.parameters(pluginName);
    const attributes = JSON.parse(parameters['Attributes']).map((attr) => JSON.parse(attr));
    const startPoints = Number(parameters['StartPoints']);
    const maxPoints = Number(parameters['MaxPoints']);
    const pointsPerLevel = Number(parameters['PointsPerLevel']);

    let discoveredNPCs = [];
    let attributePoints = startPoints;
    let attributeValues = attributes.reduce((obj, attr) => {
        obj[attr.Name] = 0;
        return obj;
    }, {});

    const _Window_MenuCommand_addMainCommands = Window_MenuCommand.prototype.addMainCommands;
    Window_MenuCommand.prototype.addMainCommands = function () {
        _Window_MenuCommand_addMainCommands.call(this);
        this.addCommand('Attribute', 'attribute', true);
    };

    const _Scene_Menu_create = Scene_Menu.prototype.create;
    Scene_Menu.prototype.create = function () {
        _Scene_Menu_create.call(this);
        this._commandWindow.setHandler('attribute', this.commandAttribute.bind(this));
    };

    Scene_Menu.prototype.commandAttribute = function () {
        SceneManager.push(Scene_Attribute);
    };

    Window_NPCList.prototype.processOk = function () {
        Window_Command.prototype.processOk.call(this);
        if (this.currentSymbol() === 'npc') {
            var npctextbox = new Window_NPCTextBox();
            this.parent.addChild(npctextbox); // Fügen Sie das Fenster zum Elternobjekt hinzu, nicht direkt zu `Window_NPCList`
        }
    };

    function Window_NPCTextBox() {
        this.initialize.apply(this, arguments);
    }

    Window_NPCTextBox.prototype = Object.create(Window_Base.prototype);
    Window_NPCTextBox.prototype.constructor = Window_NPCTextBox;

    Window_NPCTextBox.prototype.initialize = function () {
        var x = (Graphics.boxWidth - 600) / 2;
        var y = (Graphics.boxHeight - 600) / 2;
        var rect = new Rectangle(x, y, 600, 600);
        Window_Base.prototype.initialize.call(this, rect);
        this.refresh();
    };

    Window_NPCTextBox.prototype.refresh = function () {
        this.contents.clear();
        // Hier können Sie Text oder andere Elemente hinzufügen
        this.drawText('NPC Informationen', 0, 0, this.contents.width, 'center');
    };

    function Scene_Attribute() {
        this.initialize.apply(this, arguments);
    }

    Scene_Attribute.prototype = Object.create(Scene_MenuBase.prototype);
    Scene_Attribute.prototype.constructor = Scene_Attribute;

    Scene_Attribute.prototype.initialize = function () {
        Scene_MenuBase.prototype.initialize.call(this);
    };

    Scene_Attribute.prototype.create = function () {
        Scene_MenuBase.prototype.create.call(this);
        const windowWidth = Graphics.boxWidth;

        // Prozentsätze für jedes Fenster
        const attributeWindowWidthPercent = 0.3;
        const npcListWindowWidthPercent = 0.4;

        // Berechnen der Breiten basierend auf den Prozentsätzen
        const attributeWindowWidth = windowWidth * attributeWindowWidthPercent;
        const npcListWindowWidth = windowWidth * npcListWindowWidthPercent;

        // Erstellen der Fenster mit den berechneten Breiten
        const rectAttribute = new Rectangle(0, 0, attributeWindowWidth, this.mainAreaHeight());
        const rectNpcList = new Rectangle(attributeWindowWidth, 0, npcListWindowWidth, this.mainAreaHeight());
        this._attributeWindow = new Window_Attribute(rectAttribute);
        this._npcListWindow = new Window_NPCList(rectNpcList);

        // Erstellen des Command Windows
        const rectCommand = new Rectangle(attributeWindowWidth + npcListWindowWidth, 0, this.mainAreaHeight());

        this.addWindow(this._attributeWindow);
        this.addWindow(this._npcListWindow);
    };

    function Window_Attribute() {
        this.initialize.apply(this, arguments);
    }

    Window_Attribute.prototype = Object.create(Window_Base.prototype);
    Window_Attribute.prototype.constructor = Window_Attribute;

    Window_Attribute.prototype.initialize = function (rect) {
        Window_Base.prototype.initialize.call(this, rect);
        this.refresh();
    };

    Scene_Attribute.prototype.start = function () {
        Scene_MenuBase.prototype.start.call(this);
        this._attributeWindow.refresh();
    };

    Window_Attribute.prototype.refresh = function () {
        this.contents.clear();
        this.drawHeaderText();
        this.drawAttributes();
        this.drawAvailablePoints();
    };

    Window_Attribute.prototype.drawHeaderText = function () {
        this.drawText('Attribute', 0, 0, this.contents.width, 'center');
    };

    Window_Attribute.prototype.drawAttributes = function () {
        let y = this.lineHeight();
        const columnWidth = this.contents.width / 2;
        const lineHeight = this.lineHeight();
        const lineColor = '#808080'; // Grau für die Linienfarbe

        attributes.forEach((attr, index) => {
            // Zeichnet eine Linie über dem Attributnamen
            this.contents.fillRect(0, y - 2, this.contents.width, 2, lineColor);

            const attributeName = attr.Name;
            const attributeValue = attributeValues[attributeName];
            const attributeLine = `${attributeName}`;
            const pointsLine = `${attributeValue} / ${attr.MaxPoints}`;

            // Attributname linksbündig zeichnen
            this.drawText(attributeLine, 0, y, columnWidth - 2, 'left');

            // Zeichnet eine Trennlinie zwischen Attributname und Punkten
            this.contents.fillRect(columnWidth - 2, y, 2, lineHeight, lineColor);

            // Punkte zentriert zeichnen
            this.drawText(pointsLine, columnWidth, y, columnWidth, 'center');

            y += lineHeight;

            // Zeichnet eine Linie über der Beschreibung
            this.contents.fillRect(0, y - 2, this.contents.width, 2, lineColor);

            // Beschreibung direkt unter der Linie zeichnen
            this.contents.fontSize -= 2;
            this.drawText(attr.Description, 0, y, this.contents.width, 'left');
            this.contents.fontSize += 2;

            y += lineHeight;

            // Zeichnet eine Linie unter der Beschreibung
            this.contents.fillRect(0, y - 2, this.contents.width, 2, lineColor);

            // Abstand nach der Linie hinzufügen
            y += lineHeight * 0.5;
        });
    };

    function Window_NPCList() {
        this.initialize.apply(this, arguments);
    }

    Window_NPCList.prototype = Object.create(Window_Command.prototype);
    Window_NPCList.prototype.constructor = Window_NPCList;

    Window_NPCList.prototype.initialize = function (rect) {
        Window_Command.prototype.initialize.call(this, rect);
        this.refresh();
    };

    // Laden der NPC-Daten aus den Pluginparametern
    Window_NPCList.prototype.loadNPCs = function () {
        const npcData = JSON.parse(PluginManager.parameters('CrownRPGAttributes')['NPCs']);
        return npcData.map((npc) => JSON.parse(npc));
    };

    // Erstellung der NPC-Befehlsliste
    Window_NPCList.prototype.makeCommandList = function () {
        const npcs = this.loadNPCs();
        npcs.forEach((npc) => {
            this.addCommand(npc.Name, 'npc', true, npc);
        });
    };

    PluginManager.registerCommand(pluginName, 'DiscoverNPC', (args) => {
        const { NPCName } = args;
        if (!discoveredNPCs.includes(NPCName)) {
            discoveredNPCs.push(NPCName);
        }
    });

    // Zeichnen jedes Elements in der Liste
    Window_NPCList.prototype.drawItem = function (index) {
        const command = this._list[index];
        const npcName = command.name;
        const lineColor = '#808080'; // Definieren Sie die Farbe für den Trennstrich
        const rect = this.itemRect(index);
        const isDiscovered = discoveredNPCs.includes(npcName);

        //Anzeige der unentdeckten NPCs
        const bitmap = isDiscovered
            ? ImageManager.loadPicture(command.ext.BildEntdeckt)
            : ImageManager.loadPicture(command.ext.BildVerdeckt);
        const displayName = isDiscovered ? npcName : '????';
        const displayLocation = isDiscovered ? command.ext.Ort : 'Geheim';
        const displayAttribute = isDiscovered ? command.ext.Attribut : 'Unbekannt';

        const bottomPadding = 6; // Abstand zum unteren Rand des Buttons

        // Zeichnen des Bildes
        if (bitmap && bitmap.isReady()) {
            const imageWidth = 144;
            const imageHeight = 144;
            const imageX = rect.x;
            const imageY = rect.y + rect.height - imageHeight - bottomPadding;
            this.contents.blt(bitmap, 0, 0, bitmap.width, bitmap.height, imageX, imageY, imageWidth, imageHeight);
        } else if (bitmap) {
            bitmap.addLoadListener(() => {
                this.refresh();
            });
        }

        // Zeichnen des Textes
        const textX = rect.x + 144 + 8;
        const textWidth = rect.width - 144 - 16;
        const textY = rect.y + rect.height - this.lineHeight() * 3 - bottomPadding;
        const columnWidth = textWidth / 2;

        this.drawText(displayName, textX, textY, columnWidth, 'center');
        this.drawText(`Ort: ${displayLocation}`, textX + columnWidth, textY, columnWidth, 'center');
        const lineY = textY + this.lineHeight() + 2;
        this.contents.fillRect(textX, lineY, textWidth, 2, lineColor); // Trennstrich
        const attributeY = lineY + 4;
        this.drawText(`Rolle: ${displayAttribute}`, textX, attributeY, textWidth, 'left');
    };

    Window_NPCList.prototype.itemHeight = function () {
        return 150; // Setzen Sie hier die gewünschte Höhe für jeden Button
    };

    Window_NPCList.prototype.refresh = function () {
        Window_Command.prototype.refresh.call(this);
        // Hier können Sie zusätzliche Zeichnungsfunktionen hinzufügen, wie z.B. das Zeichnen von Bildern neben den NPC-Namen.
    };

    Scene_Attribute.prototype.update = function () {
        Scene_MenuBase.prototype.update.call(this);
        if (this.isActive() && this.isCancelTriggered()) {
            this.popScene();
        }
    };

    Scene_Attribute.prototype.isCancelTriggered = function () {
        return Input.isTriggered('cancel') || TouchInput.isCancelled();
    };

    Window_Attribute.prototype.drawAvailablePoints = function () {
        // Berechnet die Y-Position am unteren Rand des Fensters mit etwas Abstand
        const y = this.contents.height - this.lineHeight() - 10; // 10 Pixel Abstand vom unteren Rand
        this.drawText(`Verfügbare Punkte: ${attributePoints}`, 0, y, this.contents.width, 'left');
    };

    PluginManager.registerCommand(pluginName, 'AddPoint', (args) => {
        const { AttributeName } = args;
        if (
            attributePoints > 0 &&
            attributeValues[AttributeName] < attributes.find((attr) => attr.Name === AttributeName).MaxPoints
        ) {
            attributeValues[AttributeName]++;
            attributePoints--;
            SceneManager._scene._attributeWindow.refresh();
        }
    });

    PluginManager.registerCommand(pluginName, 'RemovePoint', (args) => {
        const { AttributeName } = args;
        if (attributeValues[AttributeName] > 0) {
            attributeValues[AttributeName]--;
            attributePoints++;
            SceneManager._scene._attributeWindow.refresh();
        }
    });

    const _Game_Actor_levelUp = Game_Actor.prototype.levelUp;
    Game_Actor.prototype.levelUp = function () {
        _Game_Actor_levelUp.call(this);
        this.gainAttributePoints(pointsPerLevel);
    };

    PluginManager.registerCommand(pluginName, 'DistributePoints', (args) => {
        const { AttributeName, Points } = args;
        const pointsToDistribute = parseInt(Points);
        const actor = $gameParty.leader(); // Annahme, dass der Anführer der Gruppe die Punkte erhält

        // Finden des Attributs basierend auf dem übergebenen Namen
        const attribute = attributes.find((attr) => attr.Name === AttributeName);

        if (
            attributePoints >= pointsToDistribute &&
            attributeValues[AttributeName] + pointsToDistribute <= actor.maxAttributePoints(AttributeName)
        ) {
            attributeValues[AttributeName] += pointsToDistribute;
            attributePoints -= pointsToDistribute;

            // Hier müssen Sie sicherstellen, dass 'attribute' existiert und eine gültige 'VariableId' hat
            if (attribute && attribute.VariableId !== undefined) {
                $gameVariables.setValue(attribute.VariableId, attributeValues[AttributeName]);
            }

            // Ersetze Platzhalter {attribute} und {points} in der Erfolgsmeldung
            let successMessage = parameters['SuccessMessage'];
            successMessage = successMessage.replace('{attribute}', AttributeName);
            successMessage = successMessage.replace('{points}', pointsToDistribute);
            successMessage = successMessage.replace('{totalPoints}', attributeValues[AttributeName]);

            $gameMessage.add(successMessage);

            AudioManager.playSe({ name: parameters['SuccessSound'], pan: 0, pitch: 100, volume: 90 });
        } else {
            AudioManager.playSe({ name: parameters['FailureSound'], pan: 0, pitch: 100, volume: 90 });
            $gameMessage.add(parameters['FailureMessage']);
        }
    });

    // Ergänzt die Game_Actor Klasse um eine Methode, die die maximalen Punkte für ein Attribut zurückgibt
    Game_Actor.prototype.maxAttributePoints = function (attributeName) {
        return attributes.find((attr) => attr.Name === attributeName).MaxPoints;
    };

    Game_Actor.prototype.gainAttributePoints = function (points) {
        attributePoints += points;
        if (attributePoints > maxPoints) {
            attributePoints = maxPoints; // Stellt sicher, dass die maximale Punktzahl nicht überschritten wird
        }
        // Aktualisieren des Attribut-Fensters, wenn es offen ist
        if (SceneManager._scene instanceof Scene_Attribute) {
            SceneManager._scene._attributeWindow.refresh();
        }
    };
})();

Mein Ziel ist es, solche Projekte zukünftig eigenständig und ohne KI-Unterstützung umsetzen zu können. Ich denke die Registrierung in diesem Forum war der erste Schritt in die richtige Richtung.
 
Hallo und willkommen im Forum!

Erstmal vorweg:
Wenn du nach einer Karriere im Bereich Spielentwicklung strebst, wirst du mit JavaScript bzw. Frontend-Webentwicklung vielleicht nicht unbedingt glücklich.
Das nur vorweg gesagt, weil du von deinen bisherigen Erfahrungen und Projekten berichtet hast und ich mir nicht sicher bin, was nun eigentlich dein Ziel ist.

Ansonsten sage ich mal Folgendes:

Schon seit längerem hege ich den Traum, das Programmieren zu erlernen, doch bisher schreckten mich die vermeintlichen Schwierigkeiten und die Annahme ab, man müsse dafür studiert haben.
Fürs Programmieren lernen benötigt man kein Studium, was jedoch nicht heißen soll, dass ein Studium nichts bringt.

Meine Erfahrungen beschränken sich bislang auf Basiskenntnisse in verschiedenen Sprachen wie Python, JavaScript und C++. Im Zuge meines aktuellen Projekts habe ich mich für JavaScript entschieden, eine Sprache, die anscheinend leicht zu erlernen, aber schwer zu meistern ist.
Ja, könnte man so sagen. :D
JavaScript bzw. Frontend-Webentwicklung im Allgemeinen ist sicherlich ein ganz guter und vor allem leichter Einstieg in die Welt der Softwareentwicklung.
Randbemerkung: In verschiedene Sprachen mal reinzuschnuppern, schadet am Anfang nicht. Früher oder später sollte man sich dann aber auf eine Sprache bzw. ein Fachgebiet konzentrieren, um effektiv zu lernen und tatsächlich auch von den Grundlagen weg zu kommen. Später, wenn man eine Sprache erstmal beherrscht, ist es dann relativ einfach, sich neue Dinge anzueignen.
Nur halt nicht alles auf einmal.

1. Ist JavaScript eine empfehlenswerte Sprache für Anfänger?
Wie schon gesagt, ja. Vorausgesetzt man kann sich das Feld Webentwicklung als zukünftige Profession vorstellen.

2. Welche Herangehensweise würdet ihr empfehlen?
3. Ist es ratsam, sich das Programmieren selbst beizubringen, oder besteht die Gefahr, sich schlechte Praktiken anzueignen?
Das kommt immer auf den Lerntyp an.
Wenn dir eigenständiges, strukturiertes Lernen liegt und es dir Spaß macht, go for it.
Wenn du mehr Unterstützung und Struktur vorgegeben brauchst, vielleicht eher nicht.
Schlechte Praktiken kann man sich sicherlich aneignen, meist beruht das aber eher auf eigenen Fehlern als den von anderen, vorausgesetzt man wählt nicht total schlechte Ressourcen als Lernquelle.

4. Könnt ihr Lernmaterialien wie Bücher, Websites oder Onlinekurse empfehlen?
Websites/Kurse:
  • MDN: https://developer.mozilla.org/en-US/
    • Gute Dokumentation/Nachschlagwerk sowie auch Guides für Anfänger
  • freeCodeCamp: https://www.freecodecamp.org/
    • Interaktiv, Schritt für Schritt die Grundlagen und auch darüber hinaus lernen
  • FrontendMasters (kostenpflichtig, außer Livestreams): https://frontendmasters.com/
    • Aufgezeichnete und Live-Kurse von erfahrenen Personen aus der Industrie (v.a. USA)
  • Nicht zu vergessen: YouTube mit zahlreichen kostenlosen Tutorials usw.
    • Gute Kanäle/Persönlichkeiten aus meiner Sicht: Kevin Powell, Wes Bos, Syntax, Coding Garden, Traversy Media, WebDevSimplified, Learn With Jason
    • Achtung: manche richten sich nicht unbedingt an Anfänger oder sind eher Unterhaltung, Fett hervorgehoben, diejenigen, die insb. auch gut für Anfänger sind
    • Tipp: Schaue dir auch die privaten Angebote der jeweiligen Personen auf deren Websites an, z.B. Kevin Powell für CSS und Wes Bos für JavaScript

Falls jemand Erfahrungen mit diesem Angebot hat, würde ich mich über Feedback freuen, insbesondere hinsichtlich der Seriosität und des Preis-Leistungs-Verhältnisses.
Kann nicht viel dazu sagen.
Habe auf die schnelle auch leider keine Preise gefunden.
Kann man machen, wenn man viel Wert auf eine Begleitung durch einen Mentor legt.
Letztendlich kann man sich das aber auch alles selbst beibringen oder z.B. mit FrontendMasters sein Geld vielleicht besser investieren, das Gelehrte dürfte sehr ähnlich sein.

Im Prinzip hängt es halt wieder von deinem Lerntyp ab. Würde bei sowas allerdings auch bedenken, dass man sich dann sehr abhängig von einer Person macht und günstig wird es wahrscheinlich auch nicht sein.
Denke vorher auf jeden Fall auch mal über andere Wege, wie z.B. ein Coding Bootcamp, sowie klassische Wege wie eine Ausbildung oder eventuell ein sehr praxisorientiertes Studium nach, wenn es da was passendes gibt.

In allen drei Fällen hat man wahrscheinlich auch einen besseren Zugang zu einem beruflichen Netzwerk als bei einer spezifischen Person, die einen auf den ultimativen Mentor macht.


PS: Weitere Infos/Empfehlungen zum Lernen von JavaScript als blutiger Anfänger auch hier in einen anderen Thema.
 
Zuletzt bearbeitet:
Zurück
Oben Unten