js继承
继承的概念我就不解释了,理解千千万,找一个属于自己的理解最不会忘
继承的主要作用就是获取属性跟方法
构造函数继承
我们新建html,编写一下js
function Person(name,age,sex){//父构造函数
this.name=name;
this.age=age;
this.sex=sex;
this.showinfo=function(){
alert('你的姓名是:'+this.name+',你今年'+this.age+'岁,你的性别是:'+this.sex);
}
}
var p1=new Person('张三',100,'男');
p1.showinfo() 输出的结果很明显
我们再写一个方法
function Worker(name,age,sex,work){//子构造函数
Person.apply(this,arguments);//在子对象构造函数中利用call或apply将父对象指向子对象的实例对象。
this.work=work;
this.showinfo=function(){
alert('你的姓名是:'+this.name+',你今年'+this.age+'岁,你的性别是:'+this.sex+',你的工作是'+this.work);
}
}
var w1=new Worker('wangwu',1000,'女','student');
alert(w1.name);//属性继承来的 ‘wangwu’
w1.showinfo();//方法也是继承来的,如果出现重名,子构造函数覆盖父构造函数的方法。。
最重要的一步就是第二行,Person.apply,改变了this这个是核心,因为参数比较多所以用apply存在数组中
混合继承
我们写一个方法,让效果更加明显,写一个元素拖拽的继承
#box{
width:100px;height:100px;background: red; position: absolute;
}
#box1{
width:100px;height:100px;background: blue; position: absolute;left: 500px; top:100px;
}
<div id="box"></div>
<div id="box1"></div> html+css 小伙伴测试可以直接复制
在js中先构造一个函数
function Drag(id){//创建一个构造函数
this.shortx=null;
this.shorty=null;
this.div=document.getElementById(id); 编写一个方法用来获取元素
}
Drag.prototype.init=function(){ 我们在函数下的原型中声明一个init方法
var that=this; 把环境赋值给that,方便调用当前环境下的方法
this.div.onmousedown=function(ev){
var ev=ev||window.event; 此处是兼容处理
that.down(ev); 调用下方的down方法
document.onmousemove=function(ev){
var ev=ev||window.event;
that.move(ev);
}
document.onmouseup=that.up;
return false;
}
Drag.prototype.down=function(ev){
this.shortx=ev.offsetX;
this.shorty=ev.offsetY;
};
Drag.prototype.move=function(ev){
this.div.style.left=ev.clientX-this.shortx+'px';
this.div.style.top=ev.clientY-this.shorty+'px';
};
Drag.prototype.up=function(){
document.onmousemove=null;
document.onmouseup=null;
};
这是面向对象编程的类似写法,不知道大家能不能看懂,简单来说就是给函数Drag原型下申明了若干个方法,这是一个很简单的元素拖动,此时我们编写好方法其实就可以使用了
var d1=new Drag('box');
d1.init();
在编辑好函数之后,申明一个构造实例对象,注意对象,属性,方法三者之间的关系,只有属性是调用方法的,对象调用属性,属性调用方法,此时id为box的div就可以拖拽了,我们看看如何继承
//混合继承:属性的继承
function Draglimit(id){
Drag.call(this,id);//属性的继承
}
这就是混合继承,通过原型加构造函数继承,先进行方法的原型声明,然后通过call的this指向
混合继承有两种方式,第一种通过赋值
//混合继承:属性的继承
function Draglimit(id){
Drag.call(this,id);//属性的继承
}
//混合继承:方法的继承1:一一赋值
for(var i in Drag.prototype){
Draglimit.prototype[i]=Drag.prototype[i];//一一赋值
}
通过for in 循环将右边的展开赋值给左边,此时我们可以通过Draglimit构造一个对象
var d2=new Draglimit('box1');
d2.init();
这样另一个div也是可以拖拽的
混合继承的第二种方式就是 原型继承
Draglimit.prototype=new Drag();//等式两边都指向同一个地方,父类和子类的构造函数全局指向父类
Draglimit.prototype.constructor=Draglimit;
看不懂的小伙伴可以看看我的原型篇
https://www.jianshu.com/p/72156bc03ac1
此时我们可以再次构造一个对象
var d2=new Draglimit('box1');
d2.init();
你会发现 也是可以拖拽的,说明我们继承成功,我们试着来编辑一下子类的私有属性
Draglimit.prototype.move=function(ev){
var l=ev.clientX-this.shortx;
var t=ev.clientY-this.shorty;
if(l<0){
l=0;
}
if(t<0){
t=0;
}
this.div.style.left=l+'px';
this.div.style.top=t+'px';
}
我给子类原型下的move重新写了一个方法,这是用来判断浏览器窗口的,防止它移出隐藏,此时子类的方法会覆盖父类的方法
大家可以参考下完整的代码 配合开始的css与div 不过核心还是在前面提到的赋值与原型
function Drag(id){//创建一个构造函数
this.shortx=null;
this.shorty=null;
this.div=document.getElementById(id);
}
Drag.prototype.init=function(){
var that=this;
this.div.onmousedown=function(ev){
var ev=ev||window.event;
that.down(ev);
document.onmousemove=function(ev){
var ev=ev||window.event;
that.move(ev);
}
document.onmouseup=that.up;
return false;
}
}
Drag.prototype.down=function(ev){
this.shortx=ev.offsetX;
this.shorty=ev.offsetY;
};
Drag.prototype.move=function(ev){
this.div.style.left=ev.clientX-this.shortx+'px';
this.div.style.top=ev.clientY-this.shorty+'px';
};
Drag.prototype.up=function(){
document.onmousemove=null;
document.onmouseup=null;
};
var d1=new Drag('box');
d1.init();
//混合继承:属性的继承
function Draglimit(id){
Drag.call(this,id);//属性的继承
}
//混合继承:方法的继承1:一一赋值
// for(var i in Drag.prototype){
// Draglimit.prototype[i]=Drag.prototype[i];//一一赋值
// }
//混合继承:方法的继承2:原型继承,父类的实例给子类的原型
Draglimit.prototype=new Drag();//等式两边都指向同一个地方,父类和子类的构造函数全局指向父类
Draglimit.prototype.constructor=Draglimit;
//子类独有的。
Draglimit.prototype.move=function(ev){
var l=ev.clientX-this.shortx;
var t=ev.clientY-this.shorty;
if(l<0){
l=0;
}
if(t<0){
t=0;
}
this.div.style.left=l+'px';
this.div.style.top=t+'px';
}
// var d1=new Drag('box');
// d1.init();
var d2=new Draglimit('box1');
d2.init();
这就是稍微有点复杂的混合继承,通过构造函数与原型的继承
最后我们来看看ES6 class 类的继承,其实继承的方法还有很多,但是这三个是比较常见也是比较全面的,希望小伙伴能好好掌握
在JavaScript中没有类的概念,只有对象。虽然现在ES6继承经常使用class关键字,这让JavaScript看起来似乎是拥有了”类”,可表面看到的不一定是本质,对程序来说,写法上面带来简便,但对内部实现来说,没有任何好处。我们称呼这种为语法糖
<style type="text/css">
#box{
width:100px;height:100px;background: red; position: absolute;
}
#box1{
width:100px;height:100px;background: blue; position: absolute;left: 500px; top:100px;
}
</style>
</head>
<body>
<div id="box"></div>
<div id="box1"></div>
css html 不变,我们使用es6的继承
class Drag{//创建一个类
constructor(id){//类的属性 constructor属性必填 其实这个属性每当我们构造对象的时候都是存在的
this.shortx=null;
this.shorty=null;
this.div=document.getElementById(id);
}
可以看看原来的对比
// function Drag(id){//创建一个构造函数
// this.shortx=null;
// this.shorty=null;
// this.div=document.getElementById(id);
// }
创建好之后,我们来构造方法
class Drag{//创建一个类
constructor(id){//类的属性
this.shortx=null;
this.shorty=null;
this.div=document.getElementById(id);
}
init(){//类的方法 注意方法写在class 中
var that=this;
this.div.onmousedown=function(ev){
var ev=ev||window.event;
that.down(ev);
document.onmousemove=function(ev){
var ev=ev||window.event;
that.move(ev);
}
document.onmouseup=that.up;
}
}
down(ev){
this.shortx=ev.offsetX;
this.shorty=ev.offsetY;
}
move(ev){
this.div.style.left=ev.clientX-this.shortx+'px';
this.div.style.top=ev.clientY-this.shorty+'px';
}
up(){
document.onmousemove=null;
document.onmouseup=null;
}
}
同样我们要实例化
var d1=new Drag('box');//通过类实例化
d1.init();
此时div已经可以拖拽了,我们看看如何继承
class Draglimit extends Drag{
constructor(id){
super(id);//将父类下面的属性和方法全局继承了
}
这就是继承的格式,同样用class 类声明 通过extends继承,这一步是最关键的,constructor跟super指代父类的参数
class Draglimit extends Drag{
constructor(id){
super(id);//将父类下面的属性和方法全局继承了
}
move(ev){
var l=ev.clientX-this.shortx;
var t=ev.clientY-this.shorty;
if(l<0){
l=0;
}
if(t<0){
t=0;
}
this.div.style.left=l+'px';
this.div.style.top=t+'px';
}
}
var d2=new Draglimit('box1');
d2.init();
同样我们给子类写个专属的,即可覆盖掉父类继承的方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style type="text/css">
#box{
width:100px;height:100px;background: red; position: absolute;
}
#box1{
width:100px;height:100px;background: blue; position: absolute;left: 500px; top:100px;
}
</style>
</head>
<body>
<div id="box"></div>
<div id="box1"></div>
</body>
<script>
class Drag{//创建一个类
constructor(id){//类的属性
this.shortx=null;
this.shorty=null;
this.div=document.getElementById(id);
}
init(){//类的方法
var that=this;
this.div.onmousedown=function(ev){
var ev=ev||window.event;
that.down(ev);
document.onmousemove=function(ev){
var ev=ev||window.event;
that.move(ev);
}
document.onmouseup=that.up;
}
}
down(ev){
this.shortx=ev.offsetX;
this.shorty=ev.offsetY;
}
move(ev){
this.div.style.left=ev.clientX-this.shortx+'px';
this.div.style.top=ev.clientY-this.shorty+'px';
}
up(){
document.onmousemove=null;
document.onmouseup=null;
}
}
var d1=new Drag('box');//通过类实例化
d1.init();
class Draglimit extends Drag{
constructor(id){
super(id);//将父类下面的属性和方法全局继承了
}
move(ev){
var l=ev.clientX-this.shortx;
var t=ev.clientY-this.shorty;
if(l<0){
l=0;
}
if(t<0){
t=0;
}
this.div.style.left=l+'px';
this.div.style.top=t+'px';
}
}
var d2=new Draglimit('box1');
d2.init();
</script>
</html>