构造函数和原型的结合应用:轻松搞定JS的面向对象编程(二)https://developer.aliyun.com/article/1426302
通过例子说明继承的实现
下面通过一个简单的例子来说明如何实现继承:
// 定义一个基础的动物类 function Animal(name, age) { // 定义动物的名称和年龄 this.name = name; this.age = age; } // 为 Animal 原型对象添加共享方法 Animal.prototype.sayHello = function() { console.log(`Hi, I am ${this.name}, I'm ${this.age} years old.`); }; // 定义一个狗类,派生于动物类 function Dog(name, age, breed) { // 调用父类的构造函数,传入名称和年龄 Animal.call(this, name, age); // 定义狗的品种 this.breed = breed; } // 让 Dog 类继承 Animal 类的原型 Dog.prototype = Object.create(Animal.prototype); Dog.prototype.constructor = Dog; // 定义 Dog 类自己的方法 Dog.prototype.bark = function() { console.log(`${this.name} barks.`); }; // 创建 Dog 实例,调用父类方法和自身方法 const dog = new Dog('Little Black', 2, 'Golden Retriever'); dog.sayHello(); // Hi, I am Little Black, I'm 2 years old. dog.bark(); // Little Black barks.
在这个例子中,我们定义了一个 Animal 类和一个 Dog 类,Dog 类派生于 Animal 类。在 Dog 类的构造函数中,我们调用了父类的构造函数 Animal.call(this, name, age),以获取来自父类的属性。同时,我们还将 Dog 类的原型对象指向 Animal 类的原型,以实现继承。在 Dog 类中,我们还定义了自己的方法 bark。
最后,我们创建了一个 Dog 实例,并调用了父类方法和自身方法,由此可以看到,Dog 实例成功地继承了 Animal 类的属性和方法,并增加了自己的方法。
VI. 面向对象与原型
介绍面向对象编程
面向对象编程(Object-oriented programming,OOP)是一种程序设计范式,它将程序中的各种功能模块(即对象)封装起来,以便于代码的复用和管理。在 OOP 中,对象是指具有特定行为、状态和标识的实体,它们封装了数据和任务,并通过相互通信来完成任务。
面向对象编程中的三个核心概念是:封装、继承和多态。封装是指将对象的状态和行为组合在一起,隐藏对象内部的细节,只向外界暴露必要的接口。继承是指一个对象可以从另一个对象继承其属性和方法,并在此基础上定制自己的行为。多态是指同一种行为可以用不同的方式实现,不同的对象可以对同一种消息作出不同的响应。
在面向对象编程中,每一个对象都有自己的属性和方法,属性是对象的状态,方法是对象的行为,它们共同组成了一个对象的整体。面向对象编程的思想是通过对一个对象进行操作来实现功能的,而不是通过操作过程来实现功能。
OOP 技术是一种非常强大的技术,它可以大幅提高代码的重用性、可扩展性和可维护性,因此在软件开发中被广泛应用。常用的 OOP 编程语言有 Java、C++、Python 等。
说明原型在面向对象中的作用
在面向对象编程中,原型是一个非常重要的概念,它是 JavaScript
中实现继承的关键。
在 JavaScript
中,每个对象都有一个原型对象,它是一个指向另一个对象的引用,这个被引用的对象就是该对象的原型。
原型对象存储了对象的属性和方法,它们是该对象的“原型”,即该对象继承的来源。在 JavaScript 中,通过原型链,我们可以实现对象之间的继承。当一个对象调用它的方法时,如果它自己没有这个方法,它会去查找它的原型对象,如果原型对象也没有这个方法,它就会去查找原型对象的原型对象,以此类推,直到找到该方法或原型链的末尾。
使用原型对象的好处是对象之间可以实现属性和方法的共享,避免了在多个对象之间重复定义相同的属性和方法,从而提高了代码的复用性和可维护性。而且,通过修改原型对象的属性和方法,可以达到对所有继承该原型对象的对象都做出相应的改变的效果,这种特性可以被用于对多个对象进行动态修改和更新。
下面是一个通过原型实现继承的例子:
// 定义一个基础的动物类 function Animal(name, age) { // 定义动物的名称和年龄 this.name = name; this.age = age; } // 为 Animal 原型对象添加共享方法 Animal.prototype.sayHello = function() { console.log(`Hi, I am ${this.name}, I'm ${this.age} years old.`); }; // 定义一个狗类,派生于动物类 function Dog(name, age, breed) { // 调用父类的构造函数,传入名称和年龄 Animal.call(this, name, age); // 定义狗的品种 this.breed = breed; } // 让 Dog 类继承 Animal 类的原型 Dog.prototype = Object.create(Animal.prototype); Dog.prototype.constructor = Dog; // 定义 Dog 类自己的方法 Dog.prototype.bark = function() { console.log(`${this.name} barks.`); }; // 创建 Dog 实例,调用父类方法和自身方法 const dog = new Dog('Little Black', 2, 'Golden Retriever'); dog.sayHello(); // Hi, I am Little Black, I'm 2 years old. dog.bark(); // Little Black barks.
在这个例子中,Animal 类定义了一个 sayHello 方法,这个方法被 Animal 的原型对象继承。而 Dog 类通过 Object.create() 方法将自己的原型指向 Animal 的原型,这样,Dog 类的实例就可以继承 Animal 的原型(包括其 sayHello 方法),并实现自己的 bark 方法。
通过例子说明面向对象和原型的结合应用
下面通过一个例子来说明面向对象和原型的结合应用:
// 定义一个基础的动物类 function Animal(name, age) { // 定义动物的名称和年龄 this.name = name; this.age = age; } // 为 Animal 原型对象添加共享方法 Animal.prototype.sayHello = function() { console.log(`Hi, I am ${this.name}, I'm ${this.age} years old.`); }; // 定义一个狗类,派生于动物类 function Dog(name, age, breed) { // 调用父类的构造函数,传入名称和年龄 Animal.call(this, name, age); // 定义狗的品种 this.breed = breed; } // 让 Dog 类继承 Animal 类的原型 Dog.prototype = Object.create(Animal.prototype); Dog.prototype.constructor = Dog; // 为 Dog 原型对象添加共享方法 Dog.prototype.bark = function() { console.log(`${this.name} barks.`); }; // 创建 Dog 实例,调用父类方法和自身方法 const dog1 = new Dog('Little Black', 2, 'Golden Retriever'); dog1.sayHello(); // Hi, I am Little Black, I'm 2 years old. dog1.bark(); // Little Black barks. // 创建另一个 Dog 实例 const dog2 = new Dog('Little White', 3, 'Husky'); dog2.sayHello(); // Hi, I am Little White, I'm 3 years old. dog2.bark(); // Little White barks.
在这个例子中,我们定义一个 Animal 类和一个 Dog 类,Dog 类派生于 Animal 类。在 Animal 类的原型对象中,我们添加了一个 sayHello 方法,在 Dog 类的原型对象中,我们添加了一个 bark 方法。这两个方法都是在原型对象中定义的,因此它们可以被所有继承该原型对象的对象共享(即所有的 Dog 实例均包含了这两个方法)。
当我们创建 Dog 类的实例时,这些实例会自动继承他们的原型对象,因此,这些实例将包含原型对象中定义的所有方法和属性(例如 sayHello
和 bark
方法)。我们在例子中创建了两个 Dog 实例,分别称为 dog1
和 dog2
, 它们都拥有 Animal 的 sayHello
方法和 Dog 的 bark
方法。
通过这种方式,我们可以将对象的属性和方法进行有效的管理,避免代码冗余和重复性代码的编写,同时提高代码的可读性和可维护性。
VII. 总结
对原型和原型链的应用做一个总结
总的来说,原型和原型链是在 JavaScript 中实现面向对象编程的基础。
- 原型是一种机制,它通过在对象中存储属性和方法,实现代码的重用。在 JavaScript 中,每个对象都会有一个原型对象,如果某个对象的属性或方法找不到,就会去它的原型对象中去查找。因此,通过利用原型,不同的对象可以共享相同的属性和方法。
- 原型链是一种继承机制,它通过将一个对象的原型设置为另一个对象,实现从父类(原型对象)到子类(继承对象)的层层继承。原型链是基于原型的继承,它可以直接使用原型对象上的方法和属性,并且可以通过继承,修改方法和属性,以实现自己的需求。
同时,原型和原型链的应用可以帮助我们有效地管理程序中大量的对象,减少代码重复,并提高代码的可读性和可维护性。以下是原型和原型链的一些具体应用:
- 使用原型实现继承,可以避免代码重复和提高代码的可维护性。
- 使用原型的共享属性和方法,可以在代码中实现更高的代码重用性和更好的性能。
- 使用原型链的方式,可以快速地继承父类的方法和属性,同时在子类上增加新的方法和属性。
- 通过修改原型对象上的属性和方法,可以实现对多个对象进行动态修改和更新。
总之,原型和原型链是 JavaScript 中的重要概念,能帮助我们更好地实现面向对象编程,同时提高代码的可维护性和可读性。在实际开发过程中,我们需要结合具体场景和需求,灵活使用原型和原型链机制,以实现更高效、简洁的代码。