javascript中的继承(JS基于原型链的继承),以及JS中的call和apply函数
2016-03-07 20:40
483 查看
1.继承是面向对象编程语言的一个重要特性,比如JAVA中,通过extend可以实现多继承,但是javascript中的继承方式跟JAVA中有很大的区别,JS中通过原型链的方式实现继承。
(1)对象的原型:因为JS中,函数也是对象,因此我们先从对象出发。什么是对象的原型,原型的定义为:
所有通过对象直接量创建的对象都具有同一个函数原型,并且可以通过Object.prototype获得对原型对象的引用,通过关键字new和构造函数调用创建的对象的原型就是构造函数的prototype属性的值。
注:没有原型的对象不多,Object.prototype对象是没有原型的。
(2)创建对象的原型
比如这里有一个Student对象和一个Person对象,其中,Student.prototype指向Person.prototype
对于创建对象完全不同的两种方法:
i)Student.prototype=Person.prototype
这种方法,创建Student的prototype对象,如果改变Student.prototype的值的时候,Person.prototype也会同时改变,为了避免这种情况,我们应采用其他方式;
ii)Student.prototype=Object.create(Person.prototype)
这种方法,创建的Student的Prototype对象,在改变Student.prototype的属性或者方法时,不会同时去改变Person.prototype的属性。
(3)基于继承的赋值操作
例1:
var o={
x:1
}
o.x=2;
alert(o.x);//输出o.x=2
例2:
var o={
x:1
}
var osp=Object.create(o);
alert(osp.x);//输出1
osp.x=2;
alert(osp.x);//输出2
i)从上面的两个例子中,我们大概可以看出来,如果对象osp上有x属性,那么无论是取值,还是赋值,都是基于osp对象上的直接属性x,如果osp对象上没有x属性,那么会沿着prototype原型链查找,直到找到一个包含x属性的prototype属性链上的对象,如果osp对象所有prototype原型链上都没有包含x属性,那么返回underfined。
ii)o对象属性的赋值,被视为在osp对象上直接进行,不会影响原型链上的属性。比如上例中的osp.x=2的赋值是在osp对象上,不会影响osp的原型对象o。
2.举一些对象中继承的例子
(1)我们学过可以用instanceof来进行类型判断,instanceof方法本来就是基于原型链的。
比如例3:
[1,2] instanceof Array //返回true
[1,2] instanceof Object //返回true
这个例子说明Array.prototype也是继承于对象而来。
(2)函数中的组合继承问题
function student(name,age){
this.name=name;
this.age=age;
}
student.prototype.age=function(){
return this.age;
}
function beststudent(name,age){
student.call(this,age);
return this.name;
}
beststudent.prototype=new student();
alert(beststudent("yu",2))//输出2
}
3.call函数和apply函数
call函数和apply函数用于改变函数中this的指向,用于对象A调用对象B的方法,call函数和apply函数的区别在于传参的类型不同,apply(x,y),x表示的是执行函数的对象,而y则表示执行函数所需要调用的参数,是一个数组,并且可以传参为argument数组,而call(x,y)中的y之后的变量则是实实在在的变量;
(1)对象的原型:因为JS中,函数也是对象,因此我们先从对象出发。什么是对象的原型,原型的定义为:
所有通过对象直接量创建的对象都具有同一个函数原型,并且可以通过Object.prototype获得对原型对象的引用,通过关键字new和构造函数调用创建的对象的原型就是构造函数的prototype属性的值。
注:没有原型的对象不多,Object.prototype对象是没有原型的。
(2)创建对象的原型
比如这里有一个Student对象和一个Person对象,其中,Student.prototype指向Person.prototype
对于创建对象完全不同的两种方法:
i)Student.prototype=Person.prototype
这种方法,创建Student的prototype对象,如果改变Student.prototype的值的时候,Person.prototype也会同时改变,为了避免这种情况,我们应采用其他方式;
ii)Student.prototype=Object.create(Person.prototype)
这种方法,创建的Student的Prototype对象,在改变Student.prototype的属性或者方法时,不会同时去改变Person.prototype的属性。
(3)基于继承的赋值操作
例1:
var o={
x:1
}
o.x=2;
alert(o.x);//输出o.x=2
例2:
var o={
x:1
}
var osp=Object.create(o);
alert(osp.x);//输出1
osp.x=2;
alert(osp.x);//输出2
i)从上面的两个例子中,我们大概可以看出来,如果对象osp上有x属性,那么无论是取值,还是赋值,都是基于osp对象上的直接属性x,如果osp对象上没有x属性,那么会沿着prototype原型链查找,直到找到一个包含x属性的prototype属性链上的对象,如果osp对象所有prototype原型链上都没有包含x属性,那么返回underfined。
ii)o对象属性的赋值,被视为在osp对象上直接进行,不会影响原型链上的属性。比如上例中的osp.x=2的赋值是在osp对象上,不会影响osp的原型对象o。
2.举一些对象中继承的例子
(1)我们学过可以用instanceof来进行类型判断,instanceof方法本来就是基于原型链的。
比如例3:
[1,2] instanceof Array //返回true
[1,2] instanceof Object //返回true
这个例子说明Array.prototype也是继承于对象而来。
(2)函数中的组合继承问题
function student(name,age){
this.name=name;
this.age=age;
}
student.prototype.age=function(){
return this.age;
}
function beststudent(name,age){
student.call(this,age);
return this.name;
}
beststudent.prototype=new student();
alert(beststudent("yu",2))//输出2
}
3.call函数和apply函数
call函数和apply函数用于改变函数中this的指向,用于对象A调用对象B的方法,call函数和apply函数的区别在于传参的类型不同,apply(x,y),x表示的是执行函数的对象,而y则表示执行函数所需要调用的参数,是一个数组,并且可以传参为argument数组,而call(x,y)中的y之后的变量则是实实在在的变量;
相关文章推荐
- JQuery1——基础($对象,选择器,对象转换)
- Android学习笔记(二九):嵌入浏览器
- Android java 与 javascript互访(相互调用)的方法例子
- JavaScript演示排序算法
- javascript实现10进制转为N进制数
- 最后一次说说闭包
- Ajax
- 2019年开发人员应该学习的8个JavaScript框架
- HTML中的script标签研究
- 对一个分号引发的错误研究
- 异步流程控制:7 行代码学会 co 模块
- ES6 走马观花(ECMAScript2015 新特性)
- JavaScript拆分字符串时产生空字符的原因
- Canvas 在高清屏下绘制图片变模糊的解决方法
- Redux系列02:一个炒鸡简单的react+redux例子
- JavaScript 各种遍历方式详解
- call/apply/bind 的理解与实例分享