[技术学习]js继承
今天又看了一遍js的面向对象方面的知识,重点看了继承相关内容,已经记不得看了第几次这个内容,终于觉得自己好像懂了,特记录下来过程。
js面向对象继承分为两大类,主要分为对象继承和非对象继承(拷贝继承),这次主要谈对象继承。对象继承主要有两种:原型继承和对象冒充继承。
一、原型继承,将子类的原型引用父类的实例,从而达到将子类的原型与父类的原型和父类的构造函数关联起来的目的。
function Person(name){
this.name=name;
}
Person.prototype.sayName=function(){
alert(this.name)
}
function Student(age){
this.age=age;
}
Student.prototype=new Person('zhangsan');//子类构造函数指向父类实例
Student.prototype.constructor=Student;//上一步指向父类实例时候,构造函数也指向父类,此处还原
var s=new Student(20);
alert(s.age); //
s.sayName(); //zhangsan
原型继承可以有效的将父类的原型和父类的构造函数里的方法均复制给子类,但是由于子类的构造函数必须指向父类实例,因此父类的成员变量无法通过子类进行实例化,如上述例子,name只能为zhangsan,无法进行子类初始化时候设置。因此我们使用第二种方法来解决此问题。
二、对象冒充法:
function Person(name){
this.name=name;
}
Person.prototype.sayName=function(){
alert(this.name)
}
function Student(name,age){
Person.call(this,name);//此处使用call进行对象冒充,将name初始化
this.age=age;
}
var s=new Student('zhangsan',20);
alert(s.name)//zhangsan
alert(s.age); //
s.sayName(); //error 不是一个方法
Person.call(this,name)对象冒充,本质是使用执行s.Person(name),将Student作为执行环境,因此this.name将赋值给Student的实例s,但是我们看到s.sayName()方法执行中报错,因此此方式无法将原型赋值给子类。
三、混合继承,结合了原型继承和对象冒充继承的优点,解决了两者的不足。
function Person(name){
this.name=name;
}
Person.prototype.sayName=function(){
alert(this.name)
}
function Student(name,age){
//对象冒充
Person.call(this,name);//此处使用call进行对象冒充,将name初始化
this.age=age;
}
//原型继承
Student.prototype=new Person();//子类构造函数指向父类实例,与直接原型继承不同,此处不需要传递参数
Student.prototype.constructor=Student;//上一步指向父类实例时候,构造函数也指向父类,此处还原
var s=new Student('zhangsan',20);
alert(s.name) //zhangsan 属性成功继承
alert(s.age); //
s.sayName(); //zhangsan 原型成功继承
混合继承完美的解决了原型和属性的继承,但是我们发现继承中父类的属性在对象冒充和原型继承中都会被引用,如果属性很多会造成大量重复引用工作,因此参考extjs的原型设计,对继承进行优化。
四、优化,设计思想核心为:
1、在extend方法,建立中转函数,将中转函数的原型指向父类原型,此时中转函数只有原型,无属性,对中转函数进行实例化,并赋值给子类,成功过滤掉父类的属性。
2、将父类的原型进行保留,可以对子类定义中的父类进行解耦,也可以在子类覆盖父类后通过引用再次调用父类方法
function extend(sub,sup){
//建立中转函数,使用原型继承
var F=new Function();
//将
F.prototype=sup.prototype;
sub.prototype=new F();
sub.prototype.constructor=sub//还原构造器
//保留父类原型对象,方便解耦,也可以获取用来父类
sub.superClass=sup.prototype
}
function Person(name,age){
this.name=name;
this.age=age;
}
Person.prototype.id=10;
Person.prototype.sayName=function(){
alert("person")
}
function Stu(name,age,no){
//使用superClass进行解耦
Stu.superClass.constructor.call(this,name,age);
this.no=no;
}
//Stu.prototype=new Person();
extend(Stu,Person);
Stu.prototype.sayName=function(){
alert("student")
}
var s=new Stu('zhangsna',10,100);
//s.sayName();
Stu.superClass.sayName.call(s);
通过深拷贝建立继承关系为jquery的继承实现方法,此次暂不讨论。
[技术学习]js继承的更多相关文章
- [技术学习]js接口继承
js是面向对象语言,但是js又缺乏了面向对象的诸多特性,比如继承,没有接口继承也没有父类继承,因此有时候需要人工来实现继承. 一.首先看下java中面向对象的继承: //定义类鸟类的飞行动作 inte ...
- [技术学习]js正则表达式汇总
一.常用正则表达式关键字 ".":任意字符 "*":任意个数 "+":任意个数,至少一个 "?":0-1个 " ...
- js继承的常用方法
写在前面的话:这篇博客不适合对面向对象一无所知的人,如果你连_proto_.prototype...都不是很了解的话,建议还是先去了解一下JavaScript面向对象的基础知识,毕竟胖子不是一口吃成的 ...
- IT软件人员的技术学习内容(写给技术迷茫中的你) - 项目管理系列文章
前面笔者曾经写过一篇关于IT从业者的职业道路文章(见笔者文:IT从业者的职业道路(从程序员到部门经理) - 项目管理系列文章).然后有读者提建议说写写技术方面的路线,所以就有了本文.本文从初学者到思想 ...
- Java多线程技术学习笔记(二)
目录: 线程间的通信示例 等待唤醒机制 等待唤醒机制的优化 线程间通信经典问题:多生产者多消费者问题 多生产多消费问题的解决 JDK1.5之后的新加锁方式 多生产多消费问题的新解决办法 sleep和w ...
- 老生常谈--Js继承小结
一直以来,对Js的继承有所认识,但是认识不全面,没什么深刻印象.于是,经常性的浪费很多时间重新看博文学习继承,今天工作不是特别忙,有幸看到了http://www.slideshare.net/stoy ...
- Js继承小结
Js继承小结 一直以来,对Js的继承有所认识,但是认识不全面,没什么深刻印象.于是,经常性的浪费很多时间重新看博文学习继承,今天工作不是特别忙,有幸看到了http://www.slideshare.n ...
- js继承之借用构造函数继承
我的上一篇文章介绍了,原型链继承模式.但是单纯的原型链模式并不能很好地实现继承. 一.原型链的缺点 1.1 单纯的原型链继承最大的一个缺点,来自于原型中包含引用类型的值. 本来,我们没有通过原型链实现 ...
- JS继承的从入门到理解
开场白 大三下学期结束时候,一个人跑到帝都来参加各厂的面试,免不了的面试过程中经常被问到的问题就是JS中如何实现继承,当时的自己也是背熟了实现继承的各种方法,回过头来想想却不知道__proto__是什 ...
随机推荐
- android学习————项目导入常见错误整理(转载)
详细请访问http://4789781.blog.51cto.com/4779781/1031107
- Volley与XUtils网络请求使用对比,心得,两者基本使用
之前一直使用的Volley作为网络请求框架,它是Google 在2013年的I/O大会 上,发布的.Volley是Android平台上的网络通信库,能使网络通信更快,更简单,更健壮,同时扩展性很强.在 ...
- 从API请求数据的方法(主要适用于tp5)
// 从api获取数据,$data是一个数组,默认为空,请求数据的方法可以通用,但是其它说明只适用于tp5 function postData($url,$data=''){ $ch = curl_i ...
- 【leetcode】Flatten Binary Tree to Linked List (middle)
Given a binary tree, flatten it to a linked list in-place. For example,Given 1 / \ 2 5 / \ \ 3 4 6 T ...
- objective-c可变数组
1 #pragma mark ---------------可变数组----------------- 2 // 可以在数组里面进行增删改的操作 3 // 4 // ...
- 启动Eclipse弹出:Failed to load JavaHL Library 错误框的解决办法
一.问题背景描述: eclipse安装完svn插件以后,在启动时出现:Failed to load JavaHL Library. These are the errors that were en ...
- Vi文档
Vi简介 Vi是一种广泛存在于各种UNIX和Linux系统中的文本编辑程序. Vi不是排版程序,只是一个纯粹的文本编辑程序. Vi是全屏幕文本编辑器,它没有菜单,只有命令. Vi不是基于窗口的,所以, ...
- Android -- getQuantityString无效
原文:http://www.xuebuyuan.com/1510993.html 原因:中文没有复数语法.
- **PHP中替换换行符
PHP中替换换行符 php 不同系统的换行不同系统之间换行的实现是不一样的linux 与unix中用 \nMAC 用 \rwindow 为了体现与linux不同 则是 \r\n所以在不同平台上 实现方 ...
- ASP.NET MVCでResponse Headerのサーバーバージョンをどうやって隠しますか?
本来是发布在客户的Wiki上的,所以用日语写. ---------------------------------------------------------------------------- ...