JavaScript几种常见的继承方法
1、call() 方法
call() 方法是与经典的对象冒充方法最相似的方法。它的第一个参数用作 this 的对象。其他参数都直接传递给函数自身
function Huster(name,idNum,college)
{
this.name = name;
this.idNum = idNum;
this.college = college;
this.course = new Array(); this.addCourse = function(course)//这个方法不能用prototype来定义,如果用的话,子类无法继承该方法
{ //用原型prototype定义的方法可以用原型链来继承,call()方法和apply()方法都无法继承
this.course.push(course);
console.log(this.course);
}; } function Autoer(name,idNum)
{
this.college = '自动化';
Huster.call(this,name,idNum,this.college);//Autoer使用call()方法来继承 Huster
if (typeof Autoer._initialized == "undefined")
{
Autoer.prototype.sayHobby = function() //自己的方法可以用原型链prototype定义
{
alert(this.college+'人喜欢撸代码!');
};
Autoer._initialized = true;
}
}
var autoer1 = new Autoer('偶人儿','U123456789'); //声明一个实例autoer1
console.log(autoer1.name,autoer1.idNum,autoer1.college,autoer1.course);
autoer1.addCourse('logistics');//调用Huster的方法
autoer1.sayHobby(); //调用自身的方法
2、apply() 方法
apply() 方法与call()方法几乎一样,唯一的区别就是apply()方法只有两个参数,第一个用作 this 的对象,第二个是要传递给函数的参数的数组。也就是说apply()方法把call()方法的若干个参数放到一个数组里,传递给父类
function Huster(name,idNum,college)
{
this.name = name;
this.idNum = idNum;
this.college = college;
this.course = new Array(); this.addCourse = function(course)//这个方法不能用prototype来定义,如果用的话,子类无法继承该方法
{ //用原型prototype定义的方法可以用原型链来继承,call()方法和apply()方法都无法继承
this.course.push(course);
console.log(this.course);
}; } function Autoer(name,idNum)
{
this.college = '自动化';
Huster.apply(this,new Array(name,idNum,this.college));//Autoer使用apply()方法来继承 Huster
if (typeof Autoer._initialized == "undefined")
{
Autoer.prototype.sayHobby = function() //自己的方法可以用原型链prototype定义
{
alert(this.college+'人喜欢撸代码!');
};
Autoer._initialized = true;
}
}
var autoer1 = new Autoer('偶人儿','U123456789'); //声明一个实例autoer1
console.log(autoer1.name,autoer1.idNum,autoer1.college,autoer1.course);
autoer1.addCourse('logistics');//调用Huster的方法
autoer1.sayHobby(); //调用自身的方法
3、原型链法(prototype chaining)
当父类的属性或方法是用原型链定义的时候,子类要用原型链法进行继承,因为父类的属性和方法是在父类的原型上面,如果用call()或者apply()方法的话,访问不到父类的属性和方法,并会报出Uncaught TypeError错误:Uncaught TypeError: autoer1.addCourse(所调用的父类的方法) is not a function;如果是属性的话,则显示undefined
下面是使用原型法继承的例子(来源于w3school教程http://www.w3school.com.cn/js/pro_js_inheritance_implementing.asp)
function ClassA() {
}
ClassA.prototype.color = "blue";
ClassA.prototype.sayColor = function () {
alert(this.color);
};
function ClassB() {
}
ClassB.prototype = new ClassA();
ClassB.prototype.name = "";
ClassB.prototype.sayName = function () {
alert(this.name);
};
var objA = new ClassA();
var objB = new ClassB();
objA.color = "blue";
objB.color = "red";
objB.name = "John";
objA.sayColor();
objB.sayColor();
objB.sayName();
注意:调用 ClassA 的构造函数,没有给它传递参数。这在原型链中是标准做法。要确保构造函数没有任何参数。
子类的所有属性和方法都必须出现在 prototype 属性被赋值后,因为在它之前赋值的所有方法都会被删除。为什么?因为 prototype 属性被替换成了新对象,添加了新方法的原始对象将被销毁。
此外,在原型链中,instanceof 运算符的运行方式也很独特。对 ClassB 的所有实例,instanceof 为 ClassA 和 ClassB 都返回 true。例如:
var objB = new ClassB();
alert(objB instanceof ClassA); //输出 "true"
alert(objB instanceof ClassB); //输出 "true"
原型链的弊端是不支持多重继承。记住,原型链会用另一类型的对象重写类的 prototype 属性。
4、混合方式
这种继承方式使用构造函数定义类,并非使用任何原型。对象冒充的主要问题是必须使用构造函数方式,这不是最好的选择。不过如果使用原型链,就无法使用带参数的构造函数了。开发者如何选择呢?答案很简单,两者都用。
在前一章,我们曾经讲解过创建类的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承 prototype 对象的方法。用这两种方式重写前面的例子,代码如下:
function Huster(name,idNum,college)
{
this.name = name;
this.idNum = idNum;
this.college = college;
this.course = new Array();
if (typeof Autoer._initialized == "undefined") //动态原型法定义addCourse()方法
{
Huster.prototype.addCourse = function(course)
{
this.course.push(course);
console.log(this.course);
};
}
} function Autoer(name,idNum)
{
this.college = '自动化';
Huster.call(this,name,idNum,this.college);//使用call()方法继承Huster的属性 if (typeof Autoer._initialized == "undefined")
{
Autoer.prototype.sayHobby = function()
{
alert(this.college+'人喜欢撸代码!');
};
Autoer._initialized = true;
} }
Autoer.prototype = new Huster(this.name);//使用原型法继承Huster的方法 var autoer1 = new Autoer('偶人儿','U123456789');
autoer1.addCourse('logistics');
console.log(autoer1.name,autoer1.idNum,autoer1.college,autoer1.course);
autoer1.sayHobby();
在此例子中,继承机制由两行突出显示的红色代码实现。在第一行突出显示的代码中,在Autoer()构造函数中,用call()方法继承 Huster 类的 idNum、college、course 属性。在第二行突出显示的代码中,用原型链继承 Huster类的方法。由于这种混合方式使用了原型链,所以 instanceof 运算符仍能正确运行。
JavaScript几种常见的继承方法的更多相关文章
- SQLMAP注入教程-11种常见SQLMAP使用方法详解
sqlmap也是渗透中常用的一个注入工具,其实在注入工具方面,一个sqlmap就足够用了,只要你用的熟,秒杀各种工具,只是一个便捷性问题,sql注入另一方面就是手工党了,这个就另当别论了.今天把我一直 ...
- [转]11种常见sqlmap使用方法详解
sqlmap也是渗透中常用的一个注入工具,其实在注入工具方面,一个sqlmap就足够用了,只要你用的熟,秒杀各种工具,只是一个便捷性问题,sql注入另一方面就是手工党了,这个就另当别论了.今天把我一直 ...
- JavaScript四种数值取整方法
一.Math.trunc() 1.定义 Math.trunc()方法去除数字的小数部分,保留整数部分. 2.语法 Math.trunc(value) 3.示例 console.log(Math.tru ...
- Android中ListView的几种常见的优化方法
Android中的ListView应该算是布局中几种最常用的组件之一了,使用也十分方便,下面将介绍ListView几种比较常见的优化方法: 首先我们给出一个没有任何优化的Listview的Adapte ...
- javascript四种类型识别的方法
× 目录 [1]typeof [2]instanceof [3]constructor[4]toString 前面的话 javascript有复杂的类型系统,类型识别则是基本的功能.javascrip ...
- Java几种常见的排序方法
日常操作中常见的排序方法有:冒泡排序.快速排序.选择排序.插入排序.希尔排序,甚至还有基数排序.鸡尾酒排序.桶排序.鸽巢排序.归并排序等. 冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一 ...
- 几种常见的排序方法总结(Python)
几种常见的排序算法总结(Python) 排序算法:是一种能将一串数据依照特定顺序进行排序的一种算法. 稳定性:稳定排序算法会让原本有相等键值的记录维持相对次序.也就是如果一个排序算法是稳定的,当有两个 ...
- Java中8种常见的排序方法
排序方法的演示1)插入排序(直接插入排序.希尔排序)2)交换排序(冒泡排序.快速排序)3)选择排序(直接选择排序.堆排序)4)归并排序5)分配排序(基数排序)所需辅助空间最多:归并排序所需辅助空间最少 ...
- 【深入JavaScript】一种JS的继承方法
这些天读了John Resig的<Secrets of JavaScript Ninja>,其中讨论到JS中实现继承的方案,非常有趣,自己探索了一下,形成了笔记,放到这里. 这个方案在Re ...
随机推荐
- Project D | Digital life
I have a dream. 1999年黑客帝国就已经提出了数字化生命的雏形,近些年的黑镜和其他科幻电影更是脑洞大开,但是生命科学的进展却差强人意. 当今人类世界里有三大复杂系统:以细胞为基础的生命 ...
- NetSec2019 20165327 Exp3 免杀原理与实践
NetSec2019 20165327 Exp3 免杀原理与实践 pre基础问题回答 一.免杀原理 一般是对恶意软件做处理,让它不被杀毒软件所检测.也是渗透测试中需要使用到的技术. 要做好免杀,就时清 ...
- HotSpot虚拟机对象探秘-笔记
学习目的:探讨HotSpot虚拟机在Java堆中对象分配.布局和访问的全过程. 1.对象的创建 虚拟机在执行到一条new指令时,先要检查指令的参数(将要实例化的类)是否已经被加载.解析.初始化过,如果 ...
- Jan.09
[10个可爱又迷人的加分俚语]1. Be in the air 将要发生的事情2. Clear the air 消除误会3. Cost an arm and a leg 极其昂贵4. A bad eg ...
- HTTPS、SSL 原理
1.1 背景知识 对称加密 :加密解密使用同一密钥,加解密速度快.随着人数增多,密钥数量急增n(n-1)/2. 非对称加密 :使用公私钥配对加解密,速度慢.公钥是从私钥中提取出来的,一般拿对方 ...
- smb 访问时 提示权限不够
1. 确认 防火墙关闭和getenforce 为Permissive 状态. 关闭防火墙 service iptables stop 关闭 setenforce 0 2.windows 登录切换 身 ...
- Java加密算法
密码的常用术语: 1.密码体制:由明文空间.密文空间.密钥空间.加密算法和解密算法5部分组成. 2.密码协议:也称为安全协议,是指以密码学为基础的消息交换的通信协议,目的是在网络环境中提供安全的服务. ...
- python 模块 不可不知的知识点
大纲可参考博客:http://www.cnblogs.com/yuanchenqi/articles/6766020.html 1.正则表达式中(re模块),. 代表除换行符以外的任意符号,但如果加上 ...
- mybatis-spring和spring版本搭配问题
所报错误:org.mybatis.spring.transaction.SpringManagedTransaction.getTimeout()Ljava/lang/Integer 匹配的版本(my ...
- webpack 简单配置
webpack.config.js const path = require('path'); const HtmlWebpackPlugin=require('html-webpack-plugin ...