35 Stimmen

javascript: was ist der Unterschied zwischen einer Funktion und einer Klasse

Ich frage mich, woran das liegt. Beide verwenden das Schlüsselwort function. Gibt es einen offensichtlichen Unterschied zwischen diesen beiden?

44voto

Esailija Punkte 134081

Technisch gesehen gibt es keine Klasse, beide sind nur Funktionen. Jede Funktion kann als Konstruktor aufgerufen werden mit dem Schlüsselwort new und die Prototypeigenschaft dieser Funktion wird für das Objekt verwendet, von dem die Methoden geerbt werden.

Der Begriff "Klasse" wird nur begrifflich verwendet, um die oben beschriebene Praxis zu beschreiben.

Wenn also jemand zu Ihnen sagt: "Machen Sie eine Farbklasse" oder was auch immer, würden Sie das tun:

function Color(r, g, b) {
    this.r = r;
    this.g = g;
    this.b = b;
}

Color.prototype.method1 = function() {

};

Color.prototype.method2 = function() {

};

Wenn Sie es aufschlüsseln, gibt es einfach eine Funktion und einige Zuweisungen zu einer Eigenschaft namens prototype dieser Funktion, alle generische Javascript-Syntax, nichts Ausgefallenes vor sich geht.

Es wird alles ein wenig magisch, wenn Sie sagen var black = new Color(0,0,0) . Sie würden dann ein Objekt mit folgenden Eigenschaften erhalten .r , .g y .b . Dieses Objekt hat auch einen versteckten [[Prototyp]]-Link zu Color.prototype . Das heißt, Sie können sagen black.method1() auch wenn .method1() existiert nicht in der black Objekt.

24voto

Yash Punkte 8318

JavaScript ist die beliebteste Implementierung des ECMAScript-Standards. Die Kernfunktionen von Javascript basieren auf dem ECMAScript-Standard, aber Javascript hat auch andere zusätzliche Funktionen, die nicht in den ECMA-Spezifikationen/Standard enthalten sind. Jeder Browser verfügt über einen Javascript-Interpreter.


Overview

" ECMAScript wurde ursprünglich als Web-Skriptsprache entwickelt, die einen Mechanismus zur Belebung von Webseiten in Browsern und zur Durchführung von Serverberechnungen als Teil einer webbasierten Client-Server-Architektur bietet. Eine Skriptsprache ist eine Programmiersprache, die zur Manipulation, Anpassung und Automatisierung der Funktionen eines bestehenden Systems verwendet wird.

ECMAScript ist eine objektorientierte Programmiersprache für die Durchführung von Berechnungen und die Bearbeitung von Rechenobjekten in einer Host-Umgebung. Ein Webbrowser bietet eine ECMAScript-Host-Umgebung für clientseitige Berechnungen, z. B. Objekte, die Fenster, Menüs, Pop-ups, Dialogfelder, Textbereiche, Anker, Frames, Verlauf, Cookies und Eingabe/Ausgabe darstellen.

ECMAScript ist objektbasiert ECMAScript: Die grundlegenden Sprach- und Host-Funktionen werden von Objekten bereitgestellt, und ein ECMAScript-Programm ist eine Ansammlung von kommunizierenden Objekten.

Objekte "

  • Jeder Konstruktor ist eine Funktion, die über eine Eigenschaft namens “prototype” die zur Umsetzung der prototypenbasierten Vererbung und der gemeinsamen Eigenschaften verwendet wird.

  • Jedes Objekt, das durch einen Konstruktor erzeugt wird, hat einen impliziten Verweis (den sogenannten Prototyp des Objekts) auf den Wert seiner constructor’s “prototype” Eigentum. Außerdem kann ein Prototyp einen impliziten Verweis auf seinen Prototyp haben, der nicht null ist, usw.; dies wird als prototype chain .


Funktion

JavaScript behandelt Funktionen als Objekte erster Klasse. Da sie ein Objekt sind, können Sie einer Funktion Eigenschaften zuweisen.

Hoisting ist die Aktion des JavaScript-Interpreters, alle Variablen- und Funktionsdeklarationen an den Anfang des aktuellen Bereichs zu verschieben. Function Hoisting, declarations & expressions

FunctionDeclaration : function BindingIdentifier ( FormalParameter ) { FunctionBody } FunctionExpression : function BindingIdentifier ( FormalParameters ) { FunctionBody }

ES5-Funktion:

function Shape(id) { // Function Declaration
    this.id = id;
};
// prototype was created automatically when we declared the function
Shape.hasOwnProperty('prototype'); // true

// Adding a prototyped method to a function.
Shape.prototype.getID = function () {
    return this.id;
};

var expFn = Shape; // Function Expression
console.dir( expFn () ); // Function Executes and return default return type - 'undefined'

Zu einer Funktion, wenn der Rückgabewert nicht angegeben ist, dann undefined zurückgegeben wird. Wird die Funktion aufgerufen mit new und der Rückgabewert ist kein Objekt, dann wird dies (das neue Objekt) zurückgegeben.

HINWEIS: Für jede Funktion wird automatisch eine Prototypeigenschaft erstellt, um die Möglichkeit zu berücksichtigen, dass die Funktion als Konstruktor verwendet wird.

  • constructor "Funktionsobjekt, das Objekte erstellt und initialisiert.
  • prototype "Objekt, das gemeinsame Eigenschaften für andere Objekte bereitstellt.
  • __proto__ " Die proto Eigenschaft, die auf den Prototyp des Superobjekts verweist. Wenn Sie es öffnen, werden Sie sehen, dass proto verweist auf die Variablen und Funktionen seines Superobjekts.

Um auf die Prototyp-Methoden der oben beschriebenen Funktion zuzugreifen, müssen wir ein Objekt mit new Schlüsselwort zusammen mit constructor function . wenn Sie Folgendes erstellen Shape - Object mit new Schlüsselwort, dann hat es ein internal (or) private link zum Prototyp der Funktion Shape .

ES5 Konstrukteur-Funktions-Klassen: Funktionsobjekte, die mit Function.prototype.bind erstellt werden

Shape.prototype.setID = function ( id ) {
    this.id = id;
};

var funObj = new Shape( );
funObj.hasOwnProperty('prototype'); // false
funObj.setID( 10 )
console.dir( funObj );

console.log( funObj.getID() );
/*
expFun                            funObj
    name: "Shape"                   id: 10
    prototype:Object
        constructor: function Shape(id)
        getID: function()
        setID: function( id )
    __proto__: function ()          __proto__: Object
                                        constructor: function Shape(id)
                                        getID: function()
                                        setID: function( id )
    <function scope>
*/

ES6 führte die Funktion Arrow ein : Ein Pfeilfunktionsausdruck hat eine kürzere Syntax als ein Funktionsausdruck und bindet nicht sein eigenes this, arguments, super oder new.target. Diese Funktionsausdrücke sind am besten für Nicht-Methodenfunktionen geeignet und können nicht als Konstruktoren verwendet werden. ArrowFunction-Grammerzeugung haben keine Prototyp-Eigenschaft.

ArrowFunction : ArrowParameters => ConciseBody

  a => (a < 10) ? 'valid' : 'invalid'

  const fn = (item) => { return item & 1 ? 'Odd' : 'Even'; };
    console.log( fn(2) ); // Even
    console.log( fn(3) ); // Odd

Klasse

In einer klassenbasierten objektorientierten Sprache wird der Zustand im Allgemeinen von Instanzen getragen, die Methoden werden von Klassen getragen, und die Vererbung bezieht sich nur auf Struktur und Verhalten. In ECMAScript werden der Zustand und die Methoden von Objekten getragen, und Struktur, Verhalten und Zustand werden alle vererbt.

Babel ist ein JavaScript-Compiler. Verwenden Sie ihn zum Transformieren ES6 a ES5 Format BABEL JS (oder) ES6Console .

ES6-Klassen : ES2015 classes sind ein einfacher Zucker für das prototypenbasierte OO-Muster. Eine einzige, praktische deklarative Form macht die Verwendung von Klassenmustern einfacher und fördert die Interoperabilität. Klassen unterstützen prototypenbasierte Vererbung, Superaufrufe, Instanz- und statische Methoden und Konstruktoren.

class Shape {
  constructor(id) {
    this.id = id
  }

  get uniqueID() {
    return this.id;
  }
  set uniqueID(changeVal) {
    this.id = changeVal;
  }
}
Shape.parent_S_V = 777;

// Class Inheritance
class Rectangle extends Shape {

  constructor(id, width, height) {
    super(id)
    this.width = width
    this.height = height
  }
  // Duplicate constructor in the same class are not allowed.
  /*constructor (width, height) { this._width  = width; this._height = height; }*/

  get area() {
    console.log('Area : ', this.width * this.height);
    return this.width * this.height
  }
  get globalValue() {
    console.log('GET ID : ', Rectangle._staticVar);
    return Rectangle._staticVar;
  }
  set globalValue(value) {
    Rectangle._staticVar = value;
    console.log('SET ID : ', Rectangle._staticVar);
  }

  static println() {
    console.log('Static Method');
  }

  // this.constructor.parent_S_V - Static property can be accessed by it's instances
  setStaticVar(staticVal) { // https://sckoverflow.com/a/42853205/5081877
    Rectangle.parent_S_V = staticVal;
    console.log('SET Instance Method Parent Class Static Value : ', Rectangle.parent_S_V);
  }

  getStaticVar() {
    console.log('GET Instance Method Parent Class Static Value : ', Rectangle.parent_S_V);
    return Rectangle.parent_S_V;
  }
}
Rectangle._staticVar = 77777;

var objTest = new Rectangle('Yash_777', 8, 7);
console.dir( objTest );

ES5 Funktionsklassen : verwendet Object.defineProperty ( O, P, Attributes )

_En Object.defineProperty() Methode definiert eine neue Eigenschaft direkt für ein Objekt oder ändert eine vorhandene Eigenschaft für ein Objekt und gibt das Objekt zurück._

Funktionsinstanzen, die als Konstruktor verwendet werden können, haben eine Prototypeigenschaft .

Diese Eigenschaft hat die Attribute { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }.

    'use strict';
var Shape = function ( superClass ) {
    var currentClass = Shape;
    _inherits(currentClass, superClass); // Prototype Chain - Extends

    function Shape(id) { superClass.call(this); // Linking with SuperClass Constructor.
        // Instance Variables list.
        this.id = id;   return this;
    }
    var staticVariablesJOSN = { "parent_S_V" : 777 };
    staticVariable( currentClass, staticVariablesJOSN );

    // Setters, Getters, instanceMethods. [{}, {}];
    var instanceFunctions = [
        {
            key: 'uniqueID',
            get: function get() { return this.id; },
            set: function set(changeVal) { this.id = changeVal; }
        }
    ];
    instanceMethods( currentClass, instanceFunctions );

    return currentClass;
}(Object);

var Rectangle = function ( superClass ) {
    var currentClass = Rectangle;

    _inherits(currentClass, superClass); // Prototype Chain - Extends

    function Rectangle(id, width, height) { superClass.call(this, id); // Linking with SuperClass Constructor.

        this.width = width;
        this.height = height;   return this;
    }

    var staticVariablesJOSN = { "_staticVar" : 77777 };
    staticVariable( currentClass, staticVariablesJOSN );

    var staticFunctions = [
        {
            key: 'println',
            value: function println() { console.log('Static Method'); }
        }
    ];
    staticMethods(currentClass, staticFunctions);

    var instanceFunctions = [
        {
            key: 'setStaticVar',
            value: function setStaticVar(staticVal) {
                currentClass.parent_S_V = staticVal;
                console.log('SET Instance Method Parent Class Static Value : ', currentClass.parent_S_V);
            }
        }, {
            key: 'getStaticVar',
            value: function getStaticVar() {
                console.log('GET Instance Method Parent Class Static Value : ', currentClass.parent_S_V);
                return currentClass.parent_S_V;
            }
        }, {
            key: 'area',
            get: function get() {
                console.log('Area : ', this.width * this.height);
                return this.width * this.height;
                }
        }, {
            key: 'globalValue',
            get: function get() {
                console.log('GET ID : ', currentClass._staticVar);
                return currentClass._staticVar;
            },
            set: function set(value) {
                currentClass._staticVar = value;
                console.log('SET ID : ', currentClass._staticVar);
            }
        }
    ];
    instanceMethods( currentClass, instanceFunctions );

    return currentClass;
}(Shape);

// ===== ES5 Class Conversion Supported Functions =====
function defineProperties(target, props) {
    console.log(target, ' : ', props);
    for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
    }
}
function staticMethods( currentClass, staticProps ) {
    defineProperties(currentClass, staticProps);
};
function instanceMethods( currentClass, protoProps ) {
    defineProperties(currentClass.prototype, protoProps);
};
function staticVariable( currentClass, staticVariales ) {
    // Get Key Set and get its corresponding value.
    // currentClass.key = value;
    for( var prop in staticVariales ) {
        console.log('Keys : Values');
        if( staticVariales.hasOwnProperty( prop ) ) {
            console.log(prop, ' : ', staticVariales[ prop ] );
            currentClass[ prop ] = staticVariales[ prop ];
        }
    }
};
function _inherits(subClass, superClass) {
    console.log( subClass, ' : extends : ', superClass );
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, 
            { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });
    if (superClass)
        Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

var objTest = new Rectangle('Yash_777', 8, 7);
console.dir(objTest);

Unten Code-Schnipsel ist zu testen, über Jede Instanz hat ihre eigene Kopie der Instanz Mitglieder und gemeinsame statische Mitglieder.

var obj1 = new Rectangle('R_1', 50, 20);
Rectangle.println(); // Static Method
console.log( obj1 );    // Rectangle {id: "R_1", width: 50, height: 20}
obj1.area;              // Area :  1000
obj1.globalValue;       // GET ID :  77777
obj1.globalValue = 88;  // SET ID :  88
obj1.globalValue;       // GET ID :  88  

var obj2 = new Rectangle('R_2', 5, 70);
console.log( obj2 );    // Rectangle {id: "R_2", width: 5, height: 70}
obj2.area;              // Area :  350    
obj2.globalValue;       // GET ID :  88
obj2.globalValue = 999; // SET ID :  999
obj2.globalValue;       // GET ID :  999

console.log('Static Variable Actions.');
obj1.globalValue;        // GET ID :  999

console.log('Parent Class Static variables');
obj1.getStaticVar();    // GET Instance Method Parent Class Static Value :  777
obj1.setStaticVar(7);   // SET Instance Method Parent Class Static Value :  7
obj1.getStaticVar();    // GET Instance Method Parent Class Static Value :  7

Die Hauptunterschiede zwischen Funktionen und Klassen sind:

  • Funktionsdeklarationen get Hoisted an den oberen Rand des Kontexts, während Klassendeklarationen und Funktionsausdrücke nicht hochgezogen werden.
  • Funktionsdeklarationen, Ausdrücke können sein Overridden denn sie sind wie eine Variable - var wenn mehrere Deklarationen verfügbar sind, hat sie Vorrang vor ihrem übergeordneten Bereich . Während die Klassen nicht überschrieben werden, sind sie wie let | const , let lässt nicht zu, dass mehrere Deklarationen mit demselben Namen innerhalb des Geltungsbereichs deklariert werden.
  • Function's / classes erlaubt nur einen einzigen Konstruktor für seinen Objektbereich.
  • Computed method names sind für ES6-Klassen mit dem Schlüsselwort class erlaubt, aber für das Schlüsselwort function ist es nicht erlaubt

    function myFoo() {
     this.['my'+'Method'] = function () { console.log('Computed Function Method'); };
    }
    class Foo {
        ['my'+'Method']() { console.log('Computed Method'); }
    }

7voto

jbabey Punkte 44325

In javascript gibt es keine Klassen. javascript verwendet Prototyp Vererbung eher als Klasse basierte Vererbung. Viele Menschen werden auf Klassen in Javascript verweisen, weil es einfacher zu verstehen ist, aber es ist nur eine Analogie.

Bei der klassenbasierten Vererbung erstellen Sie eine Klasse (eine "Blaupause", wenn Sie so wollen) und instanziieren dann Objekte aus dieser Klasse.

Bei der Vererbung von Prototypen wird ein Objekt direkt von einem anderen übergeordneten Objekt instanziiert, ohne dass jemals ein "Bauplan" benötigt wird.

Véase die wikipedia-Seite für weitere Informationen zur Vererbung von Klassen und Prototypen.

6voto

Willem van der Veen Punkte 26043

Unterschied zwischen einem Konstruktor function y class

En class Schlüsselwort in Javascript ist sehr ähnlich zu einer Konstruktor-Funktion in der folgenden Weise:

  • Sie verwenden beide das prototypische Vererbungssystem von Javascript
  • Sie werden beide zur Erstellung von Objekten mit der folgenden Syntax verwendet: new myObj(arg1, arg2)

Konstruktorfunktionen und Klassen sind sich sehr ähnlich und können oft austauschbar verwendet werden, je nach Vorliebe. Allerdings ist Javascript private Felder zu Klassen Funktionalität, die nicht durch Konstruktor-Funktionen implementiert werden kann (ohne Scope-Hacks)

Ejemplo:

class PersonClass {
  constructor(name) {
    this.name = name;
  }

  speak () { console.log('hi'); }
}

console.log(typeof PersonClass); 
// logs function, a class is a constructor function under the hood.

console.log(PersonClass.prototype.speak);
// The class's methods are placed on the prototype of the PersonClass constructor function

const me = new PersonClass('Willem');

console.log(me.name); 
// logs Willem, properties assinged in the constructor are placed on the newly created object

// The constructor function equivalent would be the following:
function PersonFunction (name) {
  this.name = name;
}

PersonFunction.prototype.speak = function () { console.log('hi'); }

2voto

Srikrushna Punkte 3387

Klasse

Eine Klassendeklaration ist auf den sie enthaltenden Block beschränkt. Es ist ein Fehler einen Klassennamen zweimal im selben Block zu deklarieren. Klassendefinitionen sind nicht gehostet.

Funktionen

Die Funktionsdeklaration ist im Strict-Modus ein Blockbereich.

Die folgende Tabelle fasst den Unterschied zwischen Klasse und Funktion zusammen enter image description here

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X