0

0

细说js继承

小云云

小云云

发布时间:2018-01-24 16:24:20

|

1697人浏览过

|

来源于php中文网

原创

为了解决包含引用类型值的原型属性会被所有实例共享的问题,大神们发明了在子类型构造函数的内部调用超类型构造函数然后通过apply()和call()方法在(将来)新创建的对象上执行构造函数的方式来实现继承,如下

function SuperType() {
    this.colors = ["red", "blue", "green"];
}
function SubType() {
//调用SuperType 并且通过call()方法修正this指向  
SuperType.call(this);
 }
var instance1 = new SubType();
instance1.colors.push("black");
//"red,blue,green,black"
alert(instance1.colors);
//"red,blue,green"
var instance2 = new SubType();
alert(instance2.colors);

以上例子中在SubType()调用了SuperType()构造函数。通过使用call()方法(或apply()方法也可以),我们实际上是在(未来将要)新创建的SubType实例的环境下调用了SuperType构造函数。这样一来,就会在新SubType对象上执行SuperType()函数中定义的所有对象初始化代码。结果,SubType的每个实例就都会具有自己的colors属性的副本了(互不影响)。

使用这种方式继承的好处:

可以在子类型构造函数中向超类型构造函数传递参数。如下

function SuperType(name) {
  this.name = name;
}
function SubType() {
//继承了SuperType,同时还传递了参数
SuperType.call(this, "Nicholas");    
//实例属性   
 this.age = 29;
}
var instance = new SubType();
  //"Nicholas";
alert(instance.name);
//29
alert(instance.age);

SuperType只接受一个参数name,该参数会直接赋给一个属性。在SubType构造函数内部调用SuperType构造函数时,实际上是为SubType的实例设置了name属性。为了确保SuperType构造函数不会重写子类型的属性,可以在调用超类型构造函数后,再添加应该在子类型中定义的属性。

使用这种方式继承的坏处:

1.方法都在构造函数中定义
 2.在超类型的原型中定义的方法,对子类型而言也是不可见的 如下

function SuperType(name) {
  this.name = name;
}
SuperType.prototype.a=function(){
    alert("aaaa");
}
function SubType() {
//继承了SuperType,同时还传递了参数
SuperType.call(this, "Nicholas");    
//实例属性
 this.age = 29;
}
var instance = new SubType();
console.log(instance);

细说js继承
我们在控制台可以看到子类型原型中无法获取超类型的a方法

二   组合继承

将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式,主要的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性。下面来看一个例子

Magician
Magician

Figma插件,AI生成图标、图片和UX文案

下载
function SuperType(name) {
  this.name = name;
  this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function() {
  alert(this.name);
};
function SubType(name, age) { 
//继承name属性    
SuperType.call(this, name);    
this.age = age;
}
//继承方法 (拼接原型链)
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function() {
  alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black"); 
//"red,blue,green,black"
alert(instance1.colors);
//"Nicholas";
instance1.sayName();
//29
instance1.sayAge();
var instance2 = new SubType("Greg", 27);
//"red,blue,green"
alert(instance2.colors);
//"27"; 
instance2.sayAge();
//"Greg"; 
instance2.sayName();

细说js继承
我们看到现在实例可以访问的超类型的原型上的方法了
SuperType构造函数定义了两个属性:name和colors。SuperType的原型定义了一个方法sayName()。Sub-Type构造函数在调用SuperType构造函数时传入了name参数,紧接着又定义了它自己的属性age。然后,将SuperType的实例赋值给SubType的原型,然后又在该新原型上定义了方法sayAge()。这样一来,就可以让两个不同的SubType实例既分别拥有自己属性——包括colors属性,又可以使用相同的方法了这种方式是目前js实现继承使用的最常见的方式

使用这种继承方式的不足

SubType.prototype = new SuperType()的确会创建一个关联到SubType.prototype 的新对象。但是它使用了SubType(..)的“构造函数调用”,如果函数SubType有一些副作用(比如写日志、修改状态、注册到其他对象、给this添加数据属性,等等)的话,就会影响到SubType()的“后代”。

改进方法

function SuperType(name) {
  this.name = name;
  this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function() {
  alert(this.name);
};
function SubType(name, age) { 
  //继承name属性    
  SuperType.call(this, name);    
  this.age = age;
}
//使用Object.create 生成对象来代替new SuperType()生成的对象

SubType.prototype = Object.create(SuperType.prototype);
SubType.prototype.sayAge = function() {
  alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
console.log(instance1 );

细说js继承
这样可以避免对SubType后代的影响

// ES6之前需要抛弃默认的SubType.prototype
SubType.ptototype = Object.create( SuperType.prototype );
// ES6开始可以直接修改现有的
SubType.prototypeObject.setPrototypeOf( SubType.prototype, SuperType.prototype );

相关推荐:

js继承 Base类的源码解析_js面向对象

JavaScript高级程序设计 阅读笔记(十四) js继承机制的实现_javascript技巧

JS继承--原型链继承和类式继承_基础知识


相关专题

更多
Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

37

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

19

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

37

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

19

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

16

2026.01.13

PHP缓存策略教程大全
PHP缓存策略教程大全

本专题整合了PHP缓存相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.13

jQuery 正则表达式相关教程
jQuery 正则表达式相关教程

本专题整合了jQuery正则表达式相关教程大全,阅读专题下面的文章了解更多详细内容。

3

2026.01.13

交互式图表和动态图表教程汇总
交互式图表和动态图表教程汇总

本专题整合了交互式图表和动态图表的相关内容,阅读专题下面的文章了解更多详细内容。

45

2026.01.13

nginx配置文件详细教程
nginx配置文件详细教程

本专题整合了nginx配置文件相关教程详细汇总,阅读专题下面的文章了解更多详细内容。

9

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 3.6万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.2万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号