Den Unterschied zwischen Object.create () und new SomeFunction () verstehen


392

Ich bin kürzlich auf die Object.create()Methode in JavaScript gestoßen und versuche herauszufinden, wie sie sich vom Erstellen einer neuen Instanz eines Objekts new SomeFunction()unterscheidet und wann Sie eine über der anderen verwenden möchten.

Betrachten Sie das folgende Beispiel:

var test = {
  val: 1,
  func: function() {
    return this.val;
  }
};
var testA = Object.create(test);

testA.val = 2;
console.log(test.func()); // 1
console.log(testA.func()); // 2

console.log('other test');
var otherTest = function() {
  this.val = 1;
  this.func = function() {
    return this.val;
  };
};

var otherTestA = new otherTest();
var otherTestB = new otherTest();
otherTestB.val = 2;
console.log(otherTestA.val); // 1 
console.log(otherTestB.val); // 2

console.log(otherTestA.func()); // 1
console.log(otherTestB.func()); // 2

Beachten Sie, dass in beiden Fällen das gleiche Verhalten beobachtet wird. Es scheint mir, dass die Hauptunterschiede zwischen diesen beiden Szenarien sind:

  • Das in verwendete Objekt Object.create()bildet tatsächlich den Prototyp des neuen Objekts, während in new Function()den deklarierten Eigenschaften / Funktionen nicht der Prototyp gebildet wird.
  • Sie können mit der Object.create()Syntax keine Verschlüsse erstellen, wie Sie es mit der funktionalen Syntax tun würden. Dies ist angesichts des lexikalischen Bereichs (vs Block) von JavaScript logisch.

Sind die obigen Aussagen richtig? Und vermisse ich etwas? Wann würden Sie eins über das andere verwenden?

BEARBEITEN: Link zur jsfiddle-Version des obigen Codebeispiels: http://jsfiddle.net/rZfYL/


Antworten:


247

Das in Object.create verwendete Objekt bildet tatsächlich den Prototyp des neuen Objekts, wobei wie im neuen Function () -Formular die deklarierten Eigenschaften / Funktionen nicht den Prototyp bilden.

Ja, erstellt Object.createein Objekt, das direkt von dem als erstes Argument übergebenen Objekt erbt.

Bei Konstruktorfunktionen erbt das neu erstellte Objekt vom Prototyp des Konstruktors, z.

var o = new SomeConstructor();

Im obigen Beispiel oerbt direkt von SomeConstructor.prototype.

Hier gibt es einen Unterschied: Object.createSie können ein Objekt erstellen, das von nichts erbt . Object.create(null);Wenn Sie jedoch festlegen, dass SomeConstructor.prototype = null;das neu erstellte Objekt von etwas erbt Object.prototype.

Sie können mit der Object.create-Syntax keine Closures erstellen, wie Sie es mit der funktionalen Syntax tun würden. Dies ist angesichts des lexikalischen Bereichs (vs Block) von JavaScript logisch.

Nun, Sie können Abschlüsse erstellen, z. B. mit dem Argument der Eigenschaftsbeschreibungen:

var o = Object.create({inherited: 1}, {
  foo: {
    get: (function () { // a closure
      var closured = 'foo';
      return function () {
        return closured+'bar';
      };
    })()
  }
});

o.foo; // "foobar"

Beachten Sie, dass ich über die ECMAScript 5th Edition- Object.createMethode spreche , nicht über die Crockford-Unterlegscheibe.

Die Methode wird in den neuesten Browsern nativ implementiert. Überprüfen Sie diese Kompatibilitätstabelle .


2
@CMS 2 Fragen. 1) Wird die Bereichskette in Object.create (null) immer noch im globalen Bereich beendet (z. B. "Fenster" in einem Browser) oder endet sie in sich selbst? 2) Mir ist immer noch nicht klar, warum Object.create eingeführt wurde (z. B. welche Funktion fehlte, die hier angesprochen wurde?) Und warum man sie anstelle der neuen Funktion () verwenden würde;
Matt

9
@ Matt, 1) der Umfang Kette ist nicht wirklich ein verwandtes Konzept hier ist Scope - Chain im Zusammenhang mit Kennung Auflösung , zum Beispiel: wie foo;in der aktuellen behoben ist lexikalische Umgebung . 2) Um die Vererbung auf einfache Weise zu implementieren, ist es ein wirklich mächtiges Konstrukt. IMO Ich würde es verwenden, weil es wirklich einfach und leicht ist, aber für Produktionscode müssen wir noch einige Zeit warten, bis ES5 weitgehend unterstützt wird. Über fehlende Funktionen, die Tatsache, dass ein "makelloses" Objekt erstellt Object.create(null);wurde, fehlte, ist es wirklich nützlich, zuverlässige Hash-Tabellen-ähnliche Objekte zu implementieren ...
CMS

@CMS Danke. Wenn Sie also einfach ein Objekt mit 'Object.create' erstellen, können Sie das Objekt auswählen, dessen Prototyp es sein soll.
Anshul

@CMS OK, Object.create(null)bedeutet also, dass Sie hasOwnProperty()beim Iterieren keinen Mist verwenden müssen, weil er keinen erbt ??? Das gefällt mir - danke. Natürlich wird es immerhasOwnProperty noch jeder tun, da nicht jeder es nutzen wird, Object.create(null)also bin ich mir nicht sicher, ob es ein wirklicher Vorteil ist ... Bisher habe ich die anderen "Vorteile" als Object.create()völlig nicht überzeugend empfunden.
user949300

425

Ganz einfach gesagt, new Xist Object.create(X.prototype)mit zusätzlich die constructorLauffunktion. (Und geben Sie dem tatsächlichen Objekt constructordie Chance, returndas Ergebnis des Ausdrucks zu sein, anstatt this.)

Das ist es. :) :)

Der Rest der Antworten ist nur verwirrend, weil anscheinend niemand sonst die Definition von beidem liest new. ;)


23
+1 Einfachheit und Klarheit! (Obwohl Object.create (null) eine nette Option zu sein scheint - sollte das vielleicht erwähnen).
user949300

Halten Sie es einfach, das ist der richtige Weg
Bill

Das läßt nur die Frage nach der „Wartezeit , so Funktionen Prototypen haben auch ? Was ist die Beziehung zwischen diesen und Objekt Prototypen?“
Qwertie

3
@Qwertie: In JS ist alles ein Objekt. :) Das haben sie von Java kopiert, der es von SmallTalk kopiert hat, der damit bis zum Ende gegangen ist. Es ist ein schöner Fall von „Auftauchen“, der das Leben im Allgemeinen erleichtert.
Evi1M4chine

@ Evi1M4chine In Java sind Funktionen keine Objekte (und auch keine Grundelemente) ... und Objekte haben keine Prototypen, daher scheint der Vergleich nicht passend zu sein. Die Tatsache, dass JS anders funktioniert als andere beliebte OO-Sprachen, ist eine Hauptverwirrungsquelle (und es hilft nicht, dass Browser keine einfache Möglichkeit bieten, das Netzwerk von Objekten einschließlich Funktionen und Prototypen zu visualisieren). PS Ich fand diesen Link hilfreich: davidwalsh.name/javascript-objects-deconstruction
Qwertie

204

Hier sind die Schritte, die intern für beide Aufrufe ausgeführt werden:
(Hinweis: Der einzige Unterschied besteht in Schritt 3)


new Test()::

  1. new Object()obj erstellen
  2. eingestellt obj.__proto__aufTest.prototype
  3. return Test.call(obj) || obj; // normally obj is returned but constructors in JS can return a value

Object.create( Test.prototype )

  1. new Object()obj erstellen
  2. eingestellt obj.__proto__aufTest.prototype
  3. return obj;

Object.createDer Konstruktor wird also im Grunde nicht ausgeführt.


@ Ray also mit object.create haben wir Schrift die Eigenschaften der Funktion in Konstruktorfunktion erwähnt?

@sortednoun Solange die Eigenschaften privat sind und nicht im Prototyp angegeben sind , werden sie nicht vererbt und Sie werden sie nicht im neuen Objekt haben (und ich würde hinzufügen, dass Sie damit rechnen können, eventuelle prototypisierte Eigenschaften zu erhalten vom übergeordneten Element, nur wenn der übergeordnete Konstruktor mindestens einmal ausgeführt wurde).
Kamafeather

Wie bei den meisten Konstruktorfunktionen werden die Methoden innerhalb des zurückgegebenen Objekts definiert. newGrundsätzlich werden alle Funktionen dupliziert, während Object.createdies nicht der Fall ist.
SparK

61

Lassen Sie mich versuchen zu erklären (mehr im Blog ):

  1. Wenn Sie schreiben CarKonstruktor var Car = function(){}, das ist , wie die Dinge sind intern: Ein Diagramm prototypischer Ketten beim Erstellen von Javascript-Objekten Wir haben einen {prototype}versteckten Link zu Function.prototypedem nicht zugänglich ist und eine prototypeVerbindung zu Car.prototypedem ist zugänglich und verfügt über eine tatsächliche constructorvon Car. Sowohl Function.prototype als auch Car.prototype haben versteckte Links zu Object.prototype.
  2. Wenn wir mit dem newOperator und der createMethode zwei äquivalente Objekte erstellen möchten, müssen wir dies folgendermaßen tun: Honda = new Car();und Maruti = Object.create(Car.prototype). Ein Diagramm prototypischer Ketten für unterschiedliche Objekterstellungsmethoden Was ist los?

    Honda = new Car();- Wenn Sie ein Objekt wie dieses erstellen, {prototype}wird auf versteckte Eigenschaften verwiesen Car.prototype. Hier wird das {prototype}Honda-Objekt also immer sein Car.prototype- wir haben keine Möglichkeit, die {prototype}Eigenschaft des Objekts zu ändern . Was ist, wenn ich den Prototyp unseres neu erstellten Objekts ändern möchte?
    Maruti = Object.create(Car.prototype)- Wenn Sie ein Objekt wie dieses erstellen, haben Sie eine zusätzliche Option, um die {prototype}Eigenschaft Ihres Objekts auszuwählen . Wenn Sie Car.prototype als möchten, übergeben Sie {prototype}es als Parameter in der Funktion. Wenn Sie keine {prototype}für Ihr Objekt möchten, können Sie nullwie folgt übergeben : Maruti = Object.create(null).

Schlussfolgerung - Mit der Methode haben Object.createSie die Freiheit, Ihre Objekteigenschaft auszuwählen {prototype}. In new Car();hast du diese Freiheit nicht.

Bevorzugter Weg in OO JavaScript:

Angenommen, wir haben zwei Objekte aund b.

var a = new Object();
var b = new Object();

Angenommen, es agibt einige Methoden, auf die bauch zugegriffen werden soll. Dafür benötigen wir eine Objektvererbung ( asollte nur dann der Prototyp sein, bwenn wir Zugriff auf diese Methoden wünschen). Wenn wir die Prototypen von aund überprüfen, werden bwir feststellen, dass sie den Prototyp gemeinsam haben Object.prototype.

Object.prototype.isPrototypeOf(b); //true
a.isPrototypeOf(b); //false (the problem comes into the picture here).

Problem - wir wollen ein Objekt aals Prototyp von b, aber hier haben wir ein Objekt bmit dem Prototyp erstellt Object.prototype. Lösung - ECMAScript 5 wurde eingeführt Object.create(), um eine solche Vererbung leicht zu erreichen. Wenn wir ein Objekt bwie dieses erstellen :

var b = Object.create(a);

dann,

a.isPrototypeOf(b);// true (problem solved, you included object a in the prototype chain of object b.)

Wenn Sie also objektorientiertes Scripting ausführen, Object.create()ist dies für die Vererbung sehr nützlich.


Es ist also etwas ähnlich wie die Objekterstellung ohne Konstruktoraufruf? Wir werden alle Vorteile der Klasse genießen. Die obj-Instanz von Class ist ebenfalls wahr. Wir rufen die Class-Funktion jedoch nicht über new auf.
Praveen

@Anshul Du hast gesagt, dass a.isPrototypeOf(b);das zurückkehren wird, falsewas richtig ist, weil beide Objekte unterschiedlich sind und auf unterschiedlichen Speicher zeigen. Der richtige Weg, dies mit dem newBediener zu tun , ist hier. - jsfiddle.net/167onunp .
Sagar Karira

Warum würden Sie nicht einfach die Prototyp-Eigenschaft von b auf a setzen, anstatt dies zu tun?
Amnestic

Hat den Artikel in Ihrem Blog auch gefallen. Hat mir geholfen, das Konzept viel besser zu verstehen. Vielen Dank.
Steady_daddy

1
Die Schlussfolgerung sagt alles.
Kushalvm

44

Diese:

var foo = new Foo();

und

var foo = Object.create(Foo.prototype);

sind ziemlich ähnlich. Ein wichtiger Unterschied besteht darin, dass new Footatsächlich Konstruktorcode ausgeführt wird, während Object.createCode wie z

function Foo() {
    alert("This constructor does not run with Object.create");
}

Beachten Sie, dass Sie mit der Zwei-Parameter-Version von Object.create()viel leistungsfähigere Dinge tun können.


1
Tolle Erklärung. Könnte ich hinzufügen, dass Sie Object.createin seiner einfachsten Form Konstruktorfunktionen aus Ihrem Code weglassen können, während Sie die Vererbung von Prototypen nutzen.
Ricky Boyce

23

Der Unterschied ist die sogenannte "pseudoklassische vs. prototypische Vererbung". Der Vorschlag ist, nur einen Typ in Ihrem Code zu verwenden und nicht beide zu mischen.

Stellen Sie sich bei der pseudoklassischen Vererbung (mit dem Operator "new") vor, Sie definieren zuerst eine Pseudoklasse und erstellen dann Objekte aus dieser Klasse. Definieren Sie beispielsweise eine Pseudoklasse "Person" und erstellen Sie dann "Alice" und "Bob" aus "Person".

Bei der prototypischen Vererbung (mit Object.create) erstellen Sie direkt eine bestimmte Person "Alice" und anschließend eine andere Person "Bob" mit "Alice" als Prototyp. Hier gibt es keine "Klasse"; Alle sind Objekte.

Intern verwendet JavaScript "prototypische Vererbung". Der "pseudoklassische" Weg ist nur etwas Zucker.

Unter diesem Link finden Sie einen Vergleich der beiden Möglichkeiten.


21
function Test(){
    this.prop1 = 'prop1';
    this.prop2 = 'prop2';
    this.func1 = function(){
        return this.prop1 + this.prop2;
    }
};

Test.prototype.protoProp1 = 'protoProp1';
Test.prototype.protoProp2 = 'protoProp2';
var newKeywordTest = new Test();
var objectCreateTest = Object.create(Test.prototype);

/* Object.create   */
console.log(objectCreateTest.prop1); // undefined
console.log(objectCreateTest.protoProp1); // protoProp1 
console.log(objectCreateTest.__proto__.protoProp1); // protoProp1

/* new    */
console.log(newKeywordTest.prop1); // prop1
console.log(newKeywordTest.__proto__.protoProp1); // protoProp1

Zusammenfassung:

1) mit newSchlüsselwort gibt es zwei Dinge zu beachten;

a) Funktion wird als Konstruktor verwendet

b) function.prototypeObjekt wird an die __proto__Eigenschaft übergeben ... oder wo __proto__es nicht unterstützt wird, ist es der zweite Ort, an dem das neue Objekt nach Eigenschaften sucht

2) mit Object.create(obj.prototype)dir konstruierst du ein Objekt ( obj.prototype) und übergibst es an das beabsichtigte Objekt .. mit dem Unterschied, dass jetzt auch neue Objekte __proto__auf obj.prototype verweisen (bitte verweise auf xj9)


15

Objekterstellungsvarianten.


Variante 1 : ' new Object () ' -> Objektkonstruktor ohne Argumente.

var p1 = new Object(); // 'new Object()' create and return empty object -> {}

var p2 = new Object(); // 'new Object()' create and return empty object -> {}

console.log(p1); // empty object -> {}

console.log(p2); // empty object -> {}

// p1 and p2 are pointers to different objects
console.log(p1 === p2); // false

console.log(p1.prototype); // undefined

// empty object which is in fact Object.prototype
console.log(p1.__proto__); // {}

// empty object to which p1.__proto__ points
console.log(Object.prototype); // {}

console.log(p1.__proto__ === Object.prototype); // true

// null, which is in fact Object.prototype.__proto__
console.log(p1.__proto__.__proto__); // null

console.log(Object.prototype.__proto__); // null

Geben Sie hier die Bildbeschreibung ein


Variante 2 : ' neues Objekt (Person) ' -> Objektkonstruktor mit Argument.

const person = {
    name: 'no name',
    lastName: 'no lastName',
    age: -1
}

// 'new Object(person)' return 'person', which is pointer to the object ->
//  -> { name: 'no name', lastName: 'no lastName', age: -1 }
var p1 = new Object(person);

// 'new Object(person)' return 'person', which is pointer to the object ->
//  -> { name: 'no name', lastName: 'no lastName', age: -1 }
var p2 = new Object(person);

// person, p1 and p2 are pointers to the same object
console.log(p1 === p2); // true
console.log(p1 === person); // true
console.log(p2 === person); // true

p1.name = 'John'; // change 'name' by 'p1'
p2.lastName = 'Doe'; // change 'lastName' by 'p2'
person.age = 25; // change 'age' by 'person'

// when print 'p1', 'p2' and 'person', it's the same result,
// because the object they points is the same
console.log(p1); // { name: 'John', lastName: 'Doe', age: 25 }
console.log(p2); // { name: 'John', lastName: 'Doe', age: 25 }
console.log(person); // { name: 'John', lastName: 'Doe', age: 25 }

Geben Sie hier die Bildbeschreibung ein


Variante 3.1 : ' Object.create (Person) '. Verwenden Sie Object.create mit dem einfachen Objekt 'person'. 'Object.create (person)' erstellt (und gibt) ein neues leeres Objekt zurück und fügt dem neuen leeren Objekt die Eigenschaft '__proto__' hinzu. Diese Eigenschaft '__proto__' zeigt auf das Objekt 'person'.

const person = {
        name: 'no name',
        lastName: 'no lastName',
        age: -1,
        getInfo: function getName() {
           return `${this.name} ${this.lastName}, ${this.age}!`;
    }
}

var p1 = Object.create(person);

var p2 = Object.create(person);

// 'p1.__proto__' and 'p2.__proto__' points to
// the same object -> 'person'
// { name: 'no name', lastName: 'no lastName', age: -1, getInfo: [Function: getName] }
console.log(p1.__proto__);
console.log(p2.__proto__);
console.log(p1.__proto__ === p2.__proto__); // true

console.log(person.__proto__); // {}(which is the Object.prototype)

// 'person', 'p1' and 'p2' are different
console.log(p1 === person); // false
console.log(p1 === p2); // false
console.log(p2 === person); // false

// { name: 'no name', lastName: 'no lastName', age: -1, getInfo: [Function: getName] }
console.log(person);

console.log(p1); // empty object - {}

console.log(p2); // empty object - {}

// add properties to object 'p1'
// (properties with the same names like in object 'person')
p1.name = 'John';
p1.lastName = 'Doe';
p1.age = 25;

// add properties to object 'p2'
// (properties with the same names like in object 'person')
p2.name = 'Tom';
p2.lastName = 'Harrison';
p2.age = 38;

// { name: 'no name', lastName: 'no lastName', age: -1, getInfo: [Function: getName] }
console.log(person);

// { name: 'John', lastName: 'Doe', age: 25 }
console.log(p1);

// { name: 'Tom', lastName: 'Harrison', age: 38 }
console.log(p2);

// use by '__proto__'(link from 'p1' to 'person'),
// person's function 'getInfo'
console.log(p1.getInfo()); // John Doe, 25!

// use by '__proto__'(link from 'p2' to 'person'),
// person's function 'getInfo'
console.log(p2.getInfo()); // Tom Harrison, 38!

Geben Sie hier die Bildbeschreibung ein


Variante 3.2 : ' Object.create (Object.prototype) '. Verwenden Sie Object.create mit integriertem Objekt -> 'Object.prototype'. 'Object.create (Object.prototype)' erstellt (und gibt) ein neues leeres Objekt zurück und fügt dem neuen leeren Objekt die Eigenschaft '__proto__' hinzu. Diese Eigenschaft '__proto__' zeigt auf das Objekt 'Object.prototype'.

// 'Object.create(Object.prototype)' :
// 1. create and return empty object -> {}.
// 2. add to 'p1' property '__proto__', which is link to 'Object.prototype'
var p1 = Object.create(Object.prototype);

// 'Object.create(Object.prototype)' :
// 1. create and return empty object -> {}.
// 2. add to 'p2' property '__proto__', which is link to 'Object.prototype'
var p2 = Object.create(Object.prototype);

console.log(p1); // {}

console.log(p2); // {}

console.log(p1 === p2); // false

console.log(p1.prototype); // undefined

console.log(p2.prototype); // undefined

console.log(p1.__proto__ === Object.prototype); // true

console.log(p2.__proto__ === Object.prototype); // true

Geben Sie hier die Bildbeschreibung ein


Variante 4 : ' new SomeFunction () '

// 'this' in constructor-function 'Person'
// represents a new instace,
// that will be created by 'new Person(...)'
// and returned implicitly
function Person(name, lastName, age) {

    this.name = name;
    this.lastName = lastName;
    this.age = age;

    //-----------------------------------------------------------------
    // !--- only for demonstration ---
    // if add function 'getInfo' into
    // constructor-function 'Person',
    // then all instances will have a copy of the function 'getInfo'!
    //
    // this.getInfo: function getInfo() {
    //  return this.name + " " + this.lastName + ", " + this.age + "!";
    // }
    //-----------------------------------------------------------------
}

// 'Person.prototype' is an empty object
// (before add function 'getInfo')
console.log(Person.prototype); // Person {}

// With 'getInfo' added to 'Person.prototype',
// instances by their properties '__proto__',
// will have access to the function 'getInfo'.
// With this approach, instances not need
// a copy of the function 'getInfo' for every instance.
Person.prototype.getInfo = function getInfo() {
    return this.name + " " + this.lastName + ", " + this.age + "!";
}

// after function 'getInfo' is added to 'Person.prototype'
console.log(Person.prototype); // Person { getInfo: [Function: getInfo] }

// create instance 'p1'
var p1 = new Person('John', 'Doe', 25);

// create instance 'p2'
var p2 = new Person('Tom', 'Harrison', 38);

// Person { name: 'John', lastName: 'Doe', age: 25 }
console.log(p1);

// Person { name: 'Tom', lastName: 'Harrison', age: 38 }
console.log(p2);

// 'p1.__proto__' points to 'Person.prototype'
console.log(p1.__proto__); // Person { getInfo: [Function: getInfo] }

// 'p2.__proto__' points to 'Person.prototype'
console.log(p2.__proto__); // Person { getInfo: [Function: getInfo] }

console.log(p1.__proto__ === p2.__proto__); // true

// 'p1' and 'p2' points to different objects(instaces of 'Person')
console.log(p1 === p2); // false

// 'p1' by its property '__proto__' reaches 'Person.prototype.getInfo' 
// and use 'getInfo' with 'p1'-instance's data
console.log(p1.getInfo()); // John Doe, 25!

// 'p2' by its property '__proto__' reaches 'Person.prototype.getInfo' 
// and use 'getInfo' with 'p2'-instance's data
console.log(p2.getInfo()); // Tom Harrison, 38!

Geben Sie hier die Bildbeschreibung ein


Schöne Zusammenfassung. Vielen Dank. Es hat mir heute geholfen !!
Anandaraja_Srinivasan

11

Intern Object.createmacht das:

Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
};

Die Syntax nimmt nur die Illusion weg, dass JavaScript die klassische Vererbung verwendet.


25
Die ECMAScript 5- Object.createMethode bietet viel mehr als das. Sie können Eigenschaften mithilfe von Eigenschaftsbeschreibungen definieren und ein Objekt erstellen, das nichts erbt ( Object.create(null);). Diese Art von Shims sollte vermieden werden, da Sie dies nicht wirklich emulieren können Verhalten auf ES3. Weitere Informationen
CMS

Stimmen Sie mit @CMS überein, aber im Allgemeinen ist es eine einfache Polyfüllung für Object.create.
V. Kovpak

10

Entsprechend dieser Antwort und diesem Video macht das new Schlüsselwort folgende Dinge:

  1. Erstellt ein neues Objekt.

  2. Verknüpft neues Objekt mit der Konstruktorfunktion ( prototype).

  3. Legt einen thisvariablen Punkt auf das neue Objekt.

  4. Führt die Konstruktorfunktion mit dem neuen Objekt und der impliziten Ausführung aus return this.

  5. Weist der Eigenschaft des neuen Objekts den Namen der Konstruktorfunktion zu constructor.

Object.createführt nur 1stund 2ndSchritte !!!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.