JS面向对象高级
思考如下问题
function Person(){
this.foot = 2;
this.head=1;
}
“人类”对象的构造函数
function Man(name){
this.name=name;
}
“男人”对象的构造函数
问题:如何使“男人”继承“人”呢?
原型链继承-prototype属性
常见的方法
Man.prototype = new Person();
Man的prototype指向一个Person的实例,所有"男人"的实例,就能继承Person了
注意
如果替换了prototype对象:o.prototype = {};
要为新的prototype对象加上constructor属性,并将这个属性指回原来的构造函数:o.prototype.constructor = o;
function Person(){
this.foot = 2;
this.head=1;
}
function Man(name){
this.name=name;
}
Man.prototype = new Person();
Man.prototype.constructor = Man;
var man = new Man("张三");
原型链继承-直接继承prototype(new一个父类的实例)
对上一种方法的改进
由于Person对象中,不变的属性都可以直接写入Person.prototype。所以,可以让Man()跳过 Person(),直接继承Person.prototype
经验
优点:效率比较高(不用执行和建立Person的实例了)
缺点:Man.prototype和Person.prototype现在指向了同一个对象,任何对Man.prototype的修改,都会反映到Person.prototype,父子集会会互相影响.
function Person(){
}
Person.prototype.foot = 2;
Person.prototype.head = 1;
function Man(name){
this.name=name;
}
Man.prototype = Person.prototype;
Man.prototype.constructor = Man;
var man1= new Man("张三");
利用空对象作为中介(不影响父集)
利用空对象作为中介
空对象,几乎不占内存
修改Student的prototype对象,不会影响到Person的prototype对象
function Person(){}
Person.prototype.foot = 2;
Person.prototype.head = 1;
function Man(name){
this.name=name;
}
var F= function(){};
F.prototype = Person.prototype;
Man.prototype = new F();
Man.prototype.constructor = Man;
var man1= new Man("张三");
利用空对象作为中介-封装为函数(可以解决重复的事情,封装完毕,我们在使用,只需要调用就可以了)
function Person(){}
Person.prototype.foot = 2;
Person.prototype.head = 1;
function Man(name){
this.name=name;
}
function extend(Child(子集),Parent(父集)){
var F= function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
extend(Man,Person);
var man1 = new Man("张三");
构造函数绑定
掌握构造函数绑定实现继承
且必须在函数里调动
他们的作用都是用来改变this的指向
call(一个一个的传参)
apply(需要使用数组来传参)
call和apply方法的异同
function.call(thisObj[, arg1[, arg2[, [,...argN]]]])调用一个对象的一个方法,以另一个对象替换当前对象。例如:B.call(A, args1,args2);即A对象调用B对象的方法
function.apply(thisObj[, argArray])应用某一对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即A对象应用B对象的方法
call和apply方法调用示例:
两方法产生的作用相同,传参不同
function Person(address,sex){
this.foot = 2;
this.head = 1;
this.address = address;
this.sex = sex;
}
function Man(name){
//使用call或apply实现继承
//Person.call(this,"北京","女");
Person.apply(this,["北京","女"]);
this.name = name;
}
var man1 = new Man("张三");
bind方法
执行完返回的是一个函数
第一个参数也是需要改变this的指向对象
和
call和apply的区别是执行完返回的是一个函数
传参的第一种方式:
obj.fn.bind(obj2,"爱爬山","爱看书")();//必须在加()调用函数
传参的第二种方式:
obj.fn.bind(obj2)("爱爬山","爱看书");
组合继承
也叫伪经典继承
将原型链继承和构造函数继承组合在一块
原型链实现对原型属性和方法的继承
借用构造函数实现对实例属性的继承
function Person(){
this.foot = 2;
this.head=1;
this.color="red";
}
Person.prototype.sayColor=function(){
alert("我爱的颜色是:"+this.color);
}
function Man(name){
Person.call(this);
this.name=name;
}
Man.prototype = new Person();
Man.prototype.constructor = Man;
var man1= new Student("张三");
var man2= new Student("李四");
拷贝继承
把父对象的所有属性和方法,拷贝进子对象
将父对象的prototype对象中的属性,一一拷贝给Child对象的prototype对象
function Person(){}
Person.prototype.foot = 2;
Person.prototype.head = 1;
Person.prototype.saySelf=function(){
alert("我有:"+this.foot+"只脚和"+this.head+"个头");
}
function Man(name){
this.name = name;
}
function extend2(Child,Parent){
var p = Parent.prototype;
var c = Child.prototype;
for(var i in p){
c[i] =p[i];
}
}
extend2(Man,Person);
var man1 = new Man("张三");
man1 .saySelf();
练习题:
创建构造函数Person,添加属性姓名(name)、语文成绩(chinese)、数学成绩(math);添加三个方法,分别返回姓名、语文和数学成绩
创建构函数Student,继承Person的属性和方法,并添加属于自己的属性年龄(age),添加属于自己的方法,返回年龄
创建Student的对象,并在页面上输出实例的姓名、语文、数学成绩和年龄
<body>
<p>姓名: <span class="name"></span></p>
<p>语文: <span class="chinese"></span></p>
<p>数学: <span class="math"></span></p>
<p>身高: <span class="height"></span></p>
<script>
var myname = document.getElementsByClassName("name")[0];
var chinese = document.getElementsByClassName("chinese")[0];
var math = document.getElementsByClassName("math")[0];
var height = document.getElementsByClassName("height")[0];
function Person() {
}
Person.prototype.name = name;
Person.prototype.chinese = chinese;
Person.prototype.math = math;
Person.prototype.names = function () {
return this.name;
}
Person.prototype.chineses = function () {
return this.chinese;
}
Person.prototype.maths = function () {
return this.math;
}
function Man(height) {
this.height = height;
}
var F = function () { };
F.prototype = Person.prototype;
Man.prototype = new F()
console.log(Man.prototype);
Man.prototype.constructor = Man;
Man.prototype.heights = function () {
return this.height;
}
var all = new Man(170)
all.name = "鹏莉"
all.chinese = "80"
all.math = "80"
all.height = "180"
myname.innerHTML = all.names();
chinese.innerHTML = all.chineses();
math.innerHTML = all.maths();
height.innerHTML = all.heights();
</script>
</body>