JavaScript伪继承实现:属性拷贝与原型链对比

作者:纸飞机时间:2026-10-22 15:37:37浏览:590

本文深入解析JavaScript中通过[[wp:a0]]模拟类的两种伪继承方式。第一种为属性继承,通过调用父类构造函数实现值类型的独立拷贝;第二种为原型继承,利用[[wp:a5]]共享对象引用。对比发现,原型链方式避免了不必要的内存复制,性能更优,是推荐的最佳实践。

本文详细介绍JavaScript中利用模拟类机制的伪继承实现方案,旨在为开发者提供实用的参考代码与原理分析。

JavaScript伪继承基础与属性继承实现

JavaScript原生环境中并不存在传统的“类”概念,但可以通过function函数来模拟类的行为。例如,我们可以定义如下结构:

第一种实现方式:属性继承。


  //该函数相当于是一个构造器,也是一个伪类
  function Fn(){
    this.a = 4;
    this.b = 5;
    this.log = function(){
      console.log(this.a,this.b);
    }
  }
  function Fn1(){
    Fn.call(this);//调用父类的构造函数
  }
  Fn1.prototype = Fn.prototype;
  var fn = new Fn();
  var fn1 = new Fn1();
  //由此可见Fn1 是fn1的子类。
  fn1 instanceof Fn; // true
  fn instanceof Fn1; // true
  fn.a = 5;
  //由此可见Fn1 继承了 Fn得所有属性和方法
  //而是是复制了一份Fn的属性和方法,并不是对象的引用。
  console.log(fn.a); // 5
  console.log(fn1.a); // 4
  this.log(); // 4 5

核心结论:该方式在内存中重新拷贝了一份属性副本,各实例间的值相互独立。修改其中一个实例的属性,不会影响另一个实例的状态。

原型继承机制与性能对比分析

第二种实现方式:原型继承(基于)。


  function Fn(){}
  Fn.prototype.data = {
    name: 'zhangsan'
  }
  Fn.prototype.getName = function(){
    return this.data.name;
  }
  function Fn1(){}
  //原型链继承
  Fn1.prototype = Fn.prototype;
  var fn = new Fn();
  var fn1 = new Fn1();
  //所用Fn1 继承了 Fn
  fn1 instanceof Fn;//true
  console.log(fn1.getName()); // zhangsan
  console.log(fn.getName()); // zhangsan
  //修改了fn的name属性值
  fn.data.name = 'lisi';
  // 由此我们可看出 原型链继承 是 引用继承
  //不会重新拷贝一份变量。就像对象的引用一样。
  console.log(fn.getName()); // lisi
  console.log(fn1.getName()); // lisi

上述两种写法在示例表现上存在显著差异。


  //第一种
  function Fn(){
    this.a = 4;
    this.b = 5;
    this.log = function(){
      console.log(this.a,this.b);
    }
  }
  var fn1 = new Fn();
  var fn2 = new Fn();
  fn1.a = 1;
  //由此可以看出两个对象互不影响
  //说明每个对象里都存在一份a和b
  fn1.log(); // 1 5
  fn2.log(); // 4 5
  //第二种
  function Fn(){}
  fn.prototype.name = 'zhangsan';
  fn.prototype.data = {
    a: 4,
    b: 5
  }
  fn.prototype.log = function(){
    console.log(this.data.a,this.data.b);
  }
  var fn1 = new Fn();
  var fn2 = new Fn();
  fn1.a = 1;
  //由此可见就算是不同的示例他们他们所指向的值是同一个。
  fn1.log();//1 5
  fn2.log();//1 5
  fn2.name = 'lisi';
  //这里fn1.name并没有被修改
  console.log(fn1.name); //zhangan
  console.log(fn2.name); // lisi

关键总结。

在类定义中直接通过this.定义的属性和方法,会被完整复制一份给子类或实例对象。因此,各个子类或实例对象之间互不干扰。

通过prototype动态增加的属性和方法,对于对象类型的数据仅保留一份引用,而值类型数据则会被复制。

核心收获。

由于函数定义具有通用性,对比上述两种方法,第二种方式(原型继承)性能明显优于第一种。因为它避免了无意义的内存复制操作,从而节省内存资源。因此,在编写类时,建议优先采用第二种方式。

如需了解更多JavaScript相关知识,可参考本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》。

希望本文的阐述能对您的JavaScript程序设计工作有所帮助。

作者最新文章