JavaScript中的原型与原型链

前言

本文将从几个代码示例来解释何为原型,何为原型链,如果你觉得本文对你有帮助的话,还望收藏,评论,点赞。🍠🍠🍠

一、🍣使用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类,也就是子对象获取了父对象的属性和方法。

graph TB Person-->Student Person-->Teacher
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指向了同一对象

一个对象的隐式原型,会指向构建出实例的类的显式原型

graph LR 对象的隐式原型-->类的显式原型

当我们在一个对象上尝试查找一个属性或者方法时,如果找不到对应的属性或者方法,就会前往隐式原型上寻找

三、🍜原型链(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的对象都是通过原型链进行属性查找的,因此优化原型链的查找效率对于提高代码的性能也具有重要意义。

相关推荐
J老熊1 小时前
Spring Cloud Netflix Eureka 注册中心讲解和案例示范
java·后端·spring·spring cloud·面试·eureka·系统架构
我爱学Python!2 小时前
面试问我LLM中的RAG,秒过!!!
人工智能·面试·llm·prompt·ai大模型·rag·大模型应用
OLDERHARD2 小时前
Java - LeetCode面试经典150题 - 矩阵 (四)
java·leetcode·面试
非著名架构师2 小时前
js混淆的方式方法
开发语言·javascript·ecmascript
银氨溶液3 小时前
MySql数据引擎InnoDB引起的锁问题
数据库·mysql·面试·求职
多多米10053 小时前
初学Vue(2)
前端·javascript·vue.js
敏编程3 小时前
网页前端开发之Javascript入门篇(5/9):函数
开发语言·javascript
看到请催我学习3 小时前
内存缓存和硬盘缓存
开发语言·前端·javascript·vue.js·缓存·ecmascript
XiaoYu20025 小时前
22.JS高级-ES6之Symbol类型与Set、Map数据结构
前端·javascript·代码规范
儒雅的烤地瓜5 小时前
JS | JS中判断数组的6种方法,你知道几个?
javascript·instanceof·判断数组·数组方法·isarray·isprototypeof