Javascript 简明教程

JavaScript - Mixins

Mixins in JavaScript

JavaScript 中的混合允许将其他对象或类的属性添加到目标对象或类的原型中,并扩展目标对象的functionality。之后,可以使用目标对象访问其他对象的method。

在 JavaScript 中,每个对象都包含一个称为 prototypeof 内置属性。原型本身就是一个对象。因此,原型对象将拥有其自己的原型属性,从而形成我们所说的原型更改。原型链有助于从其他对象继承属性和方法。

此外,可以说混合允许从其他对象或类借用functionality。

在 JavaScript 中,继承允许你扩展对象或类的功能。同样,混入也可以让你扩展对象或类的功能。

JavaScript Mixins with Objects

使用 JavaScript 混入的概念,可以通过添加其他对象的属性和方法来扩展目标对象的功能。

Syntax

下列是使用 JavaScript 混入与对象一起的语法:

Object.assign(target, obj);

在上面的语法中,我们使用 Object.assign() 方法来扩展目标对象的功能。

Parameters

  1. ` target ` - 它是你需要扩展功能的对象。

  2. ` obj ` - 它是你需要使用目标方法扩展功能的对象。

Example

在下面的代码中,父对象包含 printMessage() 函数,子对象包含 showName() 方法。这两个方法打印不同的消息。

然后,我们使用 Object.assign() 方法来扩展子对象使用父对象方法的功能。

接下来,我们只使用子对象调用父对象和子对象的不同消息,然后你可以看到输出结果。

<html>
<body>
   <p id = "output"> </p>
   <script>
      const output = document.getElementById("output");
      const parent = {
         name: "parent",
         printMessage() {
            output.innerHTML = 'This is a parent object.<br>';
         }
      }
      const child = {
         showName() {
            output.innerHTML += 'This is a child object.<br>';
         }
      }
      Object.assign(child, parent); // Mixins
      child.printMessage(); //Executing the method of parent object using child object
      child.showName();
   </script>
</body>
</html>
This is a parent object.
This is a child object.

JavaScript Mixins with Classes

你也可以使用混入通过对象来扩展类别的功能。

Syntax

我们可以遵循下面的语法来使用类的混入部分:

Object.assign(class_name.prototype, obj);

上面的语法中,我们把类的原型作为第一个参数,对象作为第二个参数,然后它们的函数需要扩展类。

Example

下面的代码中,animal 对象包含 eats 属性和 run() 方法。cat 类只包含构造函数。

我们添加 animal 对象的方法和属性添加到 cat 类的原型。然后,我们使用 cat 类的实例执行 run() 方法。

<html>
   <body>
   <p id = "output"> </p>
   <script>
      const output = document.getElementById("output");
      const animal = {
         eats: true,
         run() {
            output.innerHTML += "Animals run. <br>";
         }
      }

      class cat {
         constructor() {
            this.name = "Cat";
         }
      }
      Object.assign(cat.prototype, animal); // Mixins
      const catObj = new cat();
      output.innerHTML += "Cat eats: " + catObj.eats + "<br>";
      catObj.run();
   </script>
</body>
</html>
Cat eats: true
Animals run.

Achieving Multiple Inheritance Using the Mixins

JavaScript 不支持多重继承,这意味着扩展一个类的功能使用多个类或对象。但是,你可以使用混入来实现多重继承。

Syntax

用户可以遵循下面的语法来使用混入实现多重继承:

Object.assign(target, ob1, obj);

上面的语法将添加 obj1obj2 对象的功能添加到目标对象。

Example: Inheriting multiple objects

在下面的代码中,eat 对象包含 eatFood() 方法,而 drink 对象包含 drinkWater() 方法。

我们添加 eatdrink 对象的属性和方法到 person 对象。然后,我们使用 person 对象访问 eatFood()drinkWater() 方法。

<html>
<body>
   <div id = "demo"> </div>
   <script>
      const output = document.getElementById("demo");
      const eat = {
         eatFood() {
            output.innerHTML += "Person is eating the food! <br>";
         }
      }
      const drink = {
         drinkWater() {
            output.innerHTML += "Person is drinking water! <br>";
         }
      }
      const person = {
         name: "John",
      }
      Object.assign(person, eat, drink); // Mutiple Mixins
      person.eatFood();
      person.drinkWater();
   </script>
</body>
</html>
Person is eating the food!
Person is drinking water!

Example: Multiple Inheritance with Classes

以下实例演示了使用多个类来扩展一个类。

Entity 类是父类,它包含 state() 方法。Human 类扩展了 Entity 类并包含 walk() 方法。

Driver() 函数创建了一个新类,扩展了作为参数传递的类并在类中添加了 Drive() 方法。类似地,Swimmer() 函数创建了一个新类,扩展了用作参数传递的类的类并在类中添加了 swim() 方法。

然后,我们定义了其他几个类。person 类扩展了 Driver() 类返回的类。Driver() 函数返回了一个用 Human 类扩展的新类。同样,我们创建了 Mechanic 和 SwimmerPerson 类。

在完成此操作之后,我们创建了各种类的对象并执行了它们继承的方法。

<html>
<body>
   <p id = "demo"> </p>
   <script>
      let output = document.getElementById("demo");
      // Parent class
      class Entity {
         state() {
            return 'It is in the idle state!';
         }
      }
      // Child class
      class Human extends Entity {
         walk() {
            return 'walking on the field.';
         }
      }
      // Custom functionalities
      function Driver(parentClass) {
         return class extends parentClass {
            drive() {
               return 'driving on the road';
            }
         };
      }
      function Swimmer(parentClass) {
         return class extends parentClass {
            swim() {
               return 'swimming in water';
            }
         };
      }
      // Some other classes
      class Person extends Driver(Human) { }
      class Mechanic extends Driver(Entity) { }
      class SwimmerPerson extends Swimmer(Person) { }
      // Objects of classes
      const person = new Person();
      const personDrive = person.drive();
      const mechanic = new Mechanic();
      const mechanicDrive = mechanic.drive();

      const swimmerPerson = new SwimmerPerson();
      const swimmerDrive = swimmerPerson.drive();
      const swimmerSwim = swimmerPerson.swim();

      // Printing outputs
      output.innerHTML += 'State of the PERSON: ' + personDrive + '<br>';
      output.innerHTML += 'State of the MECHANIC: ' + mechanicDrive + '<br>';
      output.innerHTML += 'State of the SWIMMER PERSON: ' + swimmerDrive + ", " + swimmerSwim + '<br>';
   </script>
</body>
</html>
State of the PERSON: driving on the road
State of the MECHANIC: driving on the road
State of the SWIMMER PERSON: driving on the road, swimming in water

通过这种方式,你可以使用 mixin 来实现多重继承。

Benefits of using Mixins

我们在此列出了一些使用 mixin 的好处。

  1. Code reusability - 你可以借用来自其他类中其他对象的函数和属性来重用代码。

  2. Multiple inheritance - JavaScript 不支持默认情况下使用多重继承,但你可以使用 mixin 来实现类似的功能。

  3. Extensibility - 你可以使用 mixin 在不更改对象的结构或类的情况下为类或对象添加其他功能。

Limitations of Mixins

我们在此列出了一些 mixin 的局限性以及一些开发人员避免使用 mixin 的原因。

  1. Complexity - 如果过度使用 mixin,会导致代码变得复杂,在本教程的最后示例中你可以看到这一点。

  2. Pseudo inheritance - mixin 能够满足继承的要求,但不能通过使用 mixin 来实现真正的继承。

  3. Naming collision - 如果你合并多个对象,那么命名冲突的可能性很高。