JS基础继承(面向对象思想)

 

javascript继承基础

标签: javascriptclassfunctionprototypedeleteobject
  472人阅读  评论(0)  收藏  举报
  分类:

 /*(JavaScript高级程序设计读书笔记)
  javascript继承
  author:shine
*/
谁都知道封装,继承,多态是JAVA语言的三大性质,javascript虽然不是纯的JAVA语言,但它也有继承机制。

那么我们就来看看它是如何实现的吧。
一、继承的方式。
1、对象冒充:
1)单继承的对象冒充:
如:
function Class1(name) {
  this.name = name;
  this.sayHello = function() {
    alert("hello!"+this.name);
  }
}

function Class2(name,sal) {
  // 以下a.b.c三步就是对象冒充方式的核心代码
  this.newMethod = Class1;  //a 
  this.newMethod(name);  //b
  delete this.newMethod;  //c   

  this.sal = sal;
  this.showSal = function() {
     alert(name+ "的工资是"+this.sal);
  };
}

var test = new Class2("yaoyao",10000);
test.sayHello();  //output:hello!yaoyao
test.showSal();  //output:yaoyao的工资为10000

小结:
冒充对象方式:三步完成。
a.用指针指向父类函数Class1。
b.调用函数此指针的方法(有参数就传,没有就不传,但是一定要调用此方法),这就能使父类的方法

和属性成为子类的方法和属性。
c.删除指针的引用。

2)多继承的对象冒充
function Class1() {
  this.showClass1 = function() {
    alert("showClass1");
  }
}

function Class2() {
  this.showClass2 = function() {
    alert("showClass2");
  }
}

function Class3() {
  this.newMethod = Class1;  //继承Class1
  this.newMethod();
  delete this.newMethod;
  
  this.newMethod = Class2;  //继承Class2
  this.newMethod();
  delete this.newMethod;
}

var test = new Class3();
test.showClass1();
test.showClass2();

小结:
对象冒充实现多继承时有个问题,就是当Class1和Class2中的方法或属性有同名时,按照javascript的执

行顺序是后面的优先,也就是Class2优先。

总结:
传统的对象冒充是以构造函数方式来声明类的。

2.call()方法。
1)call的普通用法:
如:
function favoriteColor(name){
  alert(this.color + "是" + name + "的最爱");
}

var obj = new Object();
obj.color = "棕黄色";
sayColor.call(obj,"yaoyao");  //output:深棕色是yaoyao的最爱。
小结:
a.方法名.call()  有两个参数,第一个参数是指在哪个对象里用该方法(即:用哪个对象的资源),第二个

参数就是该方法的参数列表。(有几个写几个)。
b.call()方法并不是把方法放入某个指定的对象中,而是借用某个对象中的资源(如上例中的this.color)
来调用这个方法。

2)call的经典用法
如:
function Class1(name) {
  this.name = name;
  this.sayHello = function() {
    alert("hello!" + this.name);
  }
};

function Class2(name,sal) {
  //this.newMethod = Class1;  
  //this.newMethod(name);
  //delete this.newMethod;
  Class1.call(this,name);   //把三步简化为一步。
  
  this.sal = sal;
  this.showSal = function() {
    alert(this.name + "的工资:"+this.sal);
  }
}

var test = new Class2("yaoyao",10000);
test.sayHello();  //output:hello!yaoyao
test.showSal();  //output:yaoyao的工资是10000

3.apply()方法。
1)apply的普通用法:
function favoriteColor(num,name) {
  alert("编号为"+num+"的同学"+name + "最喜欢的颜色是"+this.color);
}

var obj = new Object();
obj.color = "棕黄色";
favoriteColor.apply(obj,new Array("1","yaoyao"));  //output:编号为1的同学yaoyao最喜欢的颜色是棕黄色
小结:
apply方法唯一的不同就是以一种数组对象的形式来传参数,有人会问那不是还麻烦些么,有了call还要

apply干嘛,呵呵继续看下去,你就会知道啦。

2)apply的经典用法:
function Class1(name) {
  this.name = name;
  this.sayHello = function() {
    alert("hello!" + this.name);
  };
};

function Class2(name,sal) {
  //this.newMethod = Class1;  
  //this.newMethod(name);
  //delete this.newMethod;
  Class1.apply(this,arguments);  //没错就是用到arguments对象
  this.sal = sal;
  this.showSal = function() {
    alert(this.name + "的工资:"+this.sal);
  };
};
小结:
看上去似乎apply加上arguments后,又比call强些,其实这里有“猫腻”,arguments是函数的参数列表对象

,如上例中的arguments指的是name,sal,那么Class1不是只要一个参数name么,没错,确实是传过

去了两个参数,但javascirpt并不做参数的检查,所以Class1会顺着取传过来的第一个参数,即name。
由此看来,使用apply加arguments时,必须使两个函数的参数顺序相同。

4.原型链
如果说上面的对象冒充,call,apply是以构造函数方式声明类,那么从名字上就应该猜到原型链自然是

以原型方式声明类。
如:
function Class1() {};
Class1.prototype.color="red";
Class1.prototype.showColor = function (){
  alert(this.color);
};

function Class2() {};
Class2.prototype = new Class1();  //关键在这里

var test = new Class2();
test.showColor();
小结:既然是原型方式,那么一样也存在着同样的问题,构造函数不能带参数。

5* 继承中同名问题。
1)
function Class1() {};
Class1.prototype.color="red";
Class1.prototype.showColor = function (){
  alert(this.color);
};

function Class2() {};
Class2.prototype = new Class1(); //a
Class2.prototype.color = "green";  //b  观察1) 2) 中a.b两句的顺序,和输出的结果
var test = new Class2();
test.showColor();  //output:green

2)
function Class1() {};
Class1.prototype.color="red";
Class1.prototype.showColor = function (){
  alert(this.color);
};

function Class2() {};
Class2.prototype.color = "green";  //b
Class2.prototype = new Class1();  //a
var test = new Class2();
test.showColor();  //output:red
小结:
你现在一定在思考为什么吧?
a.在例1中的现象是因为javascirpt中是先查找该类中所有属性和方法,如果没找到,就找该类prototype中

的类(例1中的Class1)的属性和方法,如果还找不到,就找Class1中prototype中的类的属性和方法,如

此循环下去。
b.在例2中的现象是因为所有函数的prototype都只有一个,既然a句在b句之后,所以a就把b中的同名方

法覆盖掉了。(例1从这个角度也可以解释)

6.混合方式
可能有人猜得到这就是"构造函数/原型方式" 加上了“继承” ,使用“对象冒充”来继承属性,使用“原型链”来

继承方法。这样即能排除使用“对象冒充”带来的函数的多余定义,又能避免“原型链”带来的无法带入参数

的弊端。
如:
function Class1(color){
  this.color = color;
}
Class1.prototype.showColor = function (){
  alert(this.color);
}

function Class2(color,name){
  Class1.call(this,color);  .//用“对象冒充”继承属性
  this.name = name;  
}
Class2.prototype = new Class1();  //用“原型链”继承方法
Class2.prototype.showName = function() {
  alert(this.name);
}

var test = new Class2("red","yaoyao");
test.showColor();
test.showName();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值