JavaScript - Mixin



JavaScript 中的 Mixin

JavaScript 中的 mixins 允许您将其他对象或类的属性添加到目标对象或类的原型中,并扩展目标对象的功能。之后,您可以使用目标对象访问其他对象的方法。

在 JavaScript 中,每个对象都包含一个名为 prototype 的内置属性。原型本身就是一个对象。所以 prototype 对象将有自己的 prototype 属性,从而产生我们所说的 prototype 更改。原型链有助于从其他对象继承属性和方法。

此外,你可以说 mixin 允许你从其他对象或类中借用功能。

在 JavaScript 中,继承允许您扩展对象或类的功能。同样,Mixins 还允许您扩展对象或类的功能。

JavaScript 与对象 Mixin

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

语法

以下是在 JavaScript 中将 Mixins 与对象一起使用的语法 -


 Object.assign(target, obj);

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

参数

  • target − 它是需要扩展其功能的对象。
  • obj − 它是一个对象,其功能将由目标对象扩展。

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

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

接下来,我们仅使用子对象调用 parent 和 child object 消息,您可以观察输出。


<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 Mixin 与 Classes

您还可以使用 mixin 通过对象扩展类的功能。

语法

我们可以按照下面的语法将 mixin 与 classes 一起使用 -


 Object.assign(class_name.prototype, obj);

在上面的语法中,我们将类的原型作为第一个参数传递,将对象作为第二个参数传递,其功能需要通过类进行扩展。

在下面的代码中,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.

使用 Mixin 实现多重继承

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

语法

用户可以按照下面的语法使用 mixin 实现多重继承。


 Object.assign(target, ob1, obj);

上述语法会将 obj1 和 obj2 对象的功能添加到目标对象中。

示例:继承多个对象

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

我们将 eat 和 drink 对象的属性和方法添加到 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!

示例:使用类进行多重继承

下面的示例演示了使用多个类扩展一个类。

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 实现多重继承。

使用 Mixin 的好处

在这里,我们列出了使用 mixin 的一些好处。

  • 代码可重用性 − 您可以通过从其他类的其他对象中借用方法和属性来重用代码。
  • 多重继承 − JavaScript 默认不支持多重继承,但你可以使用 mixin 实现类似的功能。
  • 可扩展性 - 您可以使用混合向类或对象添加其他功能,而无需更改对象或类的结构。

Mixin 的限制

在这里,我们列出了 mixin 的一些限制以及一些开发人员避免使用 mixin 的原因。

  • 复杂性 – 如果过度使用 mixin,则会增加代码的复杂性,如本教程的最后一个示例所示。
  • 伪继承 − mixin 可以满足继承的要求,但使用 mixin 无法实现真正的继承。
  • 命名冲突 - 如果组合多个对象,则很有可能发生命名冲突。