详解JavaScript中的原型OOP

作者:函数茶馆时间:2026-10-30 15:13:17浏览:579

本文深入解析JavaScript中的原型链机制,通过Car与Tesla类的继承示例,详细讲解prototype属性的作用、构造函数指向修正以及方法查找规则,帮助开发者理解JS面向对象编程的核心原理。

前言与原型概念

前言

JavaScript原型链对于很多刚学习JavaScript的新手来说,往往显得神秘且难以理解。然而,若想深入掌握JavaScript,研究这一机制是必经之路。尽管在实际开发中直接使用的机会不多,但机会总是留给有准备的人,下文将对此进行详细学习。

根据百度百科对property的描述:在JavaScript中,prototype对象是实现面向对象的一个重要机制。每个函数本质上都是一个Function对象,而函数对象拥有一个子对象prototype。类通过函数形式定义,prototype既表示该函数的原型,也代表一个类的成员集合。

实践中的原型链应用

实践中理解

我们在浏览器环境中进行如下实验:

前言与原型概念

可以看到,我们定义了一个名为Test的“类型”。使用typeof获取Test的类型,结果为function,这表明它是一个类。接着我们获取Test.prototype的类型,即原型的类型,结果为object,说明这是一个对象。在对象中附加一系列方法和属性,即可理解object的概念。既然确认这是一个对象,我们就可以对其进行各种操作。

请看代码:


<script>
    //来两个参数>>品牌,型号
    function Car(carBrand, model) {
      this.carBrand = carBrand;
      this.model = model;
    }
    //来一个方法>>加速方法
    Car.prototype.Acceleration = function () {
      console.log("this is " + this.carBrand + '--' + this.model);
    }
    //再来一个方法>>按喇叭
    Car.prototype.Hoot = function () {
      console.log("嘀嘀嘀");
    }
    //来一个属性>>轮子数量
    Car.prototype.Wheel = 4;

    //特斯拉>>来三个参数>>品牌,型号,动力
    function Tesla(carBrand, model ,power) {
      Car.call(this, carBrand, model);
      this.power = power;
    }

    Tesla.prototype = Object.create(Car.prototype);//创造一个空对象,并且使其原型指向参数,也就是Car.prototype.
    Tesla.prototype.constructor = Tesla; //取消不影响整体流程,但为了保持一致 特斯拉构造,如果没有此行代码,则constructor为Car

    Tesla.prototype.Acceleration = function () {
      console.log("this is " + this.carBrand + '--' + this.model+" And Drive by "+this.power);
    }
    //特斯拉独有的 GetGirl你懂的方法
    Tesla.prototype.GetGirl = function () {
      console.log('yes,fucking car...');
    }

    //特斯拉 modelX 电动
    var modelX = new Tesla("Tesla", "ModelX", "electric power");
    console.log(typeof modelX);
    modelX.Acceleration();
    console.log(modelX.Wheel);
    modelX.GetGirl();
    modelX.Hoot();
    console.log(Tesla.prototype.constructor);
  </script>

代码中包含了一系列注释,并引入了特斯拉的概念。我们定义了Car类型,创建Car对象时需要传入品牌和型号两个参数。此外,还定义了加速和鸣笛两个方法。接下来,我们希望特斯拉能够继承Car的基础方法和属性。因此,我们定义了Tesla类型,并通过call调用父类的方法。虽然此处Car仅执行赋值操作,看不出call的明显意义,但如果涉及复杂的逻辑操作后赋值(如车辆生产流程),其作用便会显现。

输出结果

查看输出结果,无需追问原因,请继续阅读后续内容。

前言与原型概念

输出结果显示为“我是特斯拉ModelX,电动车”,其他输出结果此处不再一一详述。

特斯拉的prototype原型指向了一个Car原型,为什么不直接赋值呢?原因在于直接赋值原型时,子类原型对象上附加的属性和方法会被带到父类中,导致父类被意外修改。

随后,将Tesla的原型构造指向其本身。如果不指向本身,其原型构造将默认为Car。虽然这不会影响整体流程,但为了保证一致性,仍将其原型构造保持在Tesla。此时,特斯拉拥有与父类同名的加速方法,同时也拥有了GetGirl这一自身方法。你可以手动调用并观察到,父类原型对象上并不存在子类的方法。

当子类调用父类同名方法时,系统会优先选择子类的调用。而子类Tesla若不拥有鸣笛方法,prototype会沿着原型链向父类查找,从而成功调用父类的按喇叭方法。

总结

总结

以上就是本文的全部内容,希望这些内容能对大家的JavaScript学习或工作有所帮助。如有任何疑问,欢迎留言交流。

作者最新文章