前言
本文将从几个代码示例来解释何为原型,何为原型链,如果你觉得本文对你有帮助的话,还望收藏,评论,点赞。🍠🍠🍠
一、🍣使用class实现继承
定义一个Student类
js
class Student {
//一个构造函数
constructor(name, age) {
this.name = name;
this.age = age;
}
introduce() {
console.log(`你好我是${this.name},今年${this.age}`)
}
}
const student = new Student("张三", 18)
student.introduce()
再定义一个Teacher类
js
class Teacher {
constructor(name, subject) {
this.name = name;
this.subject = subject;
}
teach() {
console.log(`我是${this.name},我教${this.subject}`)
}
}
注意:两个类都有一个相同的属性name,此时就可以用到继承来进行代码的复用
此处定义了一个Person类,其中有一个name属性,而Student类和Teacher类继承了Person类,也就是子对象获取了父对象的属性和方法。
js
class Person{
constructor(name) {
this.name=name
}
drink(){
console.log(`${this.name}在喝水`)
}
}
class Student extends Person{
constructor(name, age) {
super(name);
this.age = age;
}
introduce() {
console.log(`你好我是${this.name},今年${this.age}`)
}
}
class Teacher extends Person{
constructor(name, subject) {
super(name);
this.subject = subject;
}
teach() {
console.log(`我是${this.name},我教${this.subject}`)
}
}
const student = new Student("张三", 18)
student.introduce()
const teacher = new Teacher("李四", "js");
teacher.teach()
student.drink()
teacher.drink()
执行效果
二、🍙原型(Prototype)
原型(Prototype)是每个函数都有一个的属性,这个属性指向函数的原型对象,它被用来实现基于原型的继承。
先打印一下student这个对象
Prototype和__proto__:两者都是Object.prototype的别名,JavaScript 1.8.5之后的版本已经将__proto__属性标记为过时,建议使用prototype属性代替。
隐式原型可以通过,student.__proto__进行访问
显示原型可以通过,Student.prototype进行访问
由此可见,student.__proto__与Student.prototype指向了同一对象
一个对象的隐式原型,会指向构建出实例的类的显式原型
当我们在一个对象上尝试查找一个属性或者方法时,如果找不到对应的属性或者方法,就会前往隐式原型上寻找
三、🍜原型链(Prototype Chain)
创建一个Person类,一个Teacher类,然后让Teacher继承Person类,再实例化一个teacher对象,并调用teach()方法和drink()方法。
注意:Teacher类中并没有drink方法,同时注意其中的Object原型,下文会展示完整的原型链
js
class Person {
constructor(name) {
this.name = name
}
drink() {
console.log("喝水")
}
}
class Teacher extends Person {
constructor(name, subject) {
super(name);
this.subject = subject;
}
teach() {
console.log(`我是${this.name},我教${this.subject}`)
}
}
const teacher = new Teacher("李四", "js");
teacher.teach()
teacher.drink()
当我们访问一个对象的属性或者方法时,首先会从自身去找对应的属性或者方法,如果没有找到,就会去其指向的原型上去找,如果其指向的原型没有找到,那么就会去其原型的原型上去找,这样就形成了一条链式的结构,所以,我们将其称之为原型链。
检查一个属性或者方法是否是自身所拥有的
通过hasOwnProperty可以检验一个属性或者方法是否属于对象本身,其中,name属性属于teacher对象,而teach方法则不属于
js
const teacher = new Teacher("李四", "js");
console.log(teacher.hasOwnProperty("name"))
console.log(teacher.hasOwnProperty("teach"))
那么hasOwnProperty()方法又是哪儿来的呢?
完整的原型链:
其中hasOwnPrototype方法便是来自Object原型
四、🍟使用instanceof作类型判断
使用之前的代码,运行,并在浏览器打开控制台
js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
class Person {
constructor(name) {
this.name = name
}
drink() {
console.log("喝水")
}
}
class Teacher extends Person {
constructor(name, subject) {
super(name);
this.subject = subject;
}
teach() {
console.log(`我是${this.name},我教${this.subject}`)
}
}
const teacher = new Teacher("李四", "js");
</script>
</body>
</html>
其中,Teacher,Person,Object都是存在于一条原型链上,而Array不存在于这条原型链上,所有作类型判断时为false
判断一个数组
定义一个数组[],然后展开可见其原型为Array
再使用instanceof进行判断
对象也是同理,其原型为Object,在使用instanceof进行判断时为true
注意:我们日常说js中万物皆为对象的原因时,所有数据的原型都是Object
总结
理解原型和原型链是掌握JavaScript面向对象编程的关键。通过原型链,子类可以继承父类的属性和方法,同时也能够拥有自己的属性和方法。在实际开发中,我们可以利用原型链实现代码的复用和扩展。同时,由于JavaScript的对象都是通过原型链进行属性查找的,因此优化原型链的查找效率对于提高代码的性能也具有重要意义。