Ⅰ js class继承问题,希望new出子类的时候自动调用从父类继承来的方法
1.把父类的这个方法改成private 2.如果是需要一个子类可以其它子类不可以的话,那你就要考虑这样的继承是否合理了。 3.如果觉得合理并且有这钟需要的话,方法一:在父类前面不要加任何修饰符。然后子类和调用类移到 其它包里 。方法二:空方法(取巧的做法)
Ⅱ 在js中,子类如何调用父类中方法如下图示:
//子类Student
function Student(name,age,sex,phone){
//继承方法
Person.call(this,name,age);
//添加自己的属性
this.sex=sex;
this.phone=phone;
//添加自己的方法
this.say();
}
//继承父类的属性
for(var i in Person.prototype){
Student.prototype[i]=Person.prototype[i];
}
//重写父类方法
Student.prototype.say()
{
alert(this.phone+' 'this.sex);
}
Ⅲ javascript实现继承有哪些方式
Javascript的继承在很多书里面细致的分了很多种类型和实现方式,大体上就是两种:对象冒充、原型方式。这两种方式各有优点和缺陷,这里我给你先列举出来,再从底层分析区别:
(一)对象冒充
function A(name){
this.name = name;
this.sayHello = function(){alert(this.name+” say Hello!”);};
}
function B(name,id){
this.temp = A;
this.temp(name); //相当于new A();
delete this.temp; //防止在以后通过temp引用覆盖超类A的属性和方法
this.id = id;
this.checkId = function(ID){alert(this.id==ID)};
}
当构造对象B的时候,调用temp相当于启动A的构造函数,注意这里的上下文环境中的this对象是B的实例,所以在执行A构造函数脚本时,所有A的变量 和方法都会赋值给this所指的对象,即B的实例,这样子就达到B继承了A的属性方法的目的。之后删除临时引用temp,是防止维护B中对A的类对象(注 意不是实例对象)的引用更改,因为更改temp会直接导致类A(注意不是类A的对象)结构的变化。
我们看到了,在Js版本更新的过程中,为了更方便的执行这种上下文this的切换以达到继承或者更加广义的目的,增加了call和apply函数。它们的 原理是一样的,只是参数不同的版本罢了(一个可变任意参数,一个必须传入数组作为参数集合)。这里就以call为例子,解释一下用call实现的对象冒充 继承。
function Rect(width, height){
this.width = width;
this.height = height;
this.area = function(){return this.width*this.height;};
}
function myRect(width, height, name){
Rect .call(this,width,height);
this.name = name;
this.show = function(){
alert(this.name+” with area:”+this.area());
}
}
关于Call方法,官方解释:调用一个对象的一个方法,以另一个对象替换当前对象。
call (thisOb,arg1, arg2…)
这也是一种对象冒充的继承,其实在call方法调用的时候发生的事情也是上下文环境变量this的替换,在myRect函数体中this肯定是指向类 myRect对象的实例了,然而用这个this作为上下文环境变量调用名字叫Rect方法,即类Rect的构造函数。于是此时调用Rect时候对this 的赋值属性和方法都实际上是对一个myRect的对象进行。所以说尽管call和apply并不是仅仅为了继承而新增的方法,但用它们可以模拟继承。
对象冒充继承就是这么一回事,它可以实现多重继承,只要重复做这一套赋值的流程就可以了。不过目前真正大规模使用得并不多,为什么呢?因为它有一个明显的 性能缺陷,这就要说道OO的概念了,我们说对象是成员+成员方法的集合,构造对象实例的时候,这些实例只需要拥有各自的成员变量就可以了,成员方法只是一 段对变量操作的可执行文本区域而已,这段区域不用为每个实例而复制一份,所有的实例都可以共享。现在回到Js利用对象冒充模拟的继承里,所有的成员方法都 是针对this而创建的,也就是所所有的实例都会拥有一份成员方法的副本,这是对内存资源的一种极度浪费。其它的缺陷比如说对象冒充无法继承 prototype域的变量和方法就不用提了,笔者认为前一个致命缺陷就已经足够。不过,我们还是需要理解它,特别是父类的属性和方法是如何继承下来的原 理,对于理解Js继承很重要。
(二)原型方式
第二种继承方式是原型方式,所谓原型方式的继承,是指利用了prototype或者说以某种方式覆盖了prototype,从而达到属性方法复制的目的。 其实现方式有很多中,可能不同框架多少会有一点区别,但是我们把握住原理,就不会有任何不理解的地方了。看一个例子(某一种实现):
function Person(){
this.name = “Mike”;
this.sayGoodbye = function(){alert(“GoodBye!”);};
}
Person.prototype.sayHello = function(){alert(”Hello!”);};
function Student(){}
Student.prototype = new Person();
关键是对最后一句Student原型属性赋值为Person类构造的对象,这里笔者解释一下父类的属性和方法是如何到子类上的。Js对象在读取某 个对象属性的时候,总是先查看自身域的属性列表,如果有就返回否则去读取prototype域(每个对象共享构造对象的类的prototype域所有属性 和方法),如果找到就返回,由于prototype可以指向别的对象,所以Js解释器会递归的去查找prototype域指向对象的prototype 域,直到prototype为本身,查找变成了一种循环,就停止,此时还没找到就成undefined了。
这样看来,最后一句发生的效果就是将父类所有属性和方法连接到子类的prototype域上,这样子类就继承了父类所有的属性和方法,包括name、 sayGoodbye和sayHello。这里与其把最后一句看成一种赋值,不如理解成一种指向关系更好一点。这种原型继承的缺陷也相当明显,就是继承时 父类的构造函数时不能带参数,因为对子类prototype域的修改是在声明子类对象之后才能进行,用子类构造函数的参数去初始化父类属性是无法实现的, 如下所示:
function Person(name){
this.name = name;
}
function Student(name,id){
this.id = id;
}
Student.prototype = new Person(this.name);
两种继承方式已经讲完了,如果我们理解了两种方式下子类如何把父类的属性和方法“抓取”下来,就可以自由组合各自的利弊,来实现真正合理的Js继承。下面是个人总结的一种综合方式:
function Person(name){
this.name = name;
}
Person.prototype.sayHello = function(){alert(this.name+“say Hello!”);};
function Student(name,id){
Person.call(this,name);
this.id = id;
}
Student.prototype = new Person();
Student.prototype.show = function(){
alert(“Name is:”+ this.name+” and Id is:”+this.id);
}
总结就是利用对象冒充机制的call方法把父类的属性给抓取下来,而成员方法尽量写进被所有对象实例共享的prototype域中,以防止方法副本重复创 建。然后子类继承父类prototype域来抓取下来所有的方法。如想彻底理清这些调用链的关系,推荐大家多关注Js中prototype的 constructor和对象的constructor属性,这里就不多说了。
Ⅳ javascript有哪些方法能够实现继承
JavaScript中要实现继承,其实就是实现三层含义:
1、子类的实例可以共享父类的方法;
2、子类可以覆盖父类的方法或者扩展新的方法;
3、子类和父类都是子类实例的“类型”。
JavaScript中,并不直接从语法上支持继承,但是可以通过模拟的方法来实现继承,以下是关于实现继承的几种方法的总结:
1、构造继承法
2、原型继承法
3、实例继承法
4、拷贝继承法
1、构造继承法:
在子类中执行父类的构造函数。
1<SCRIPT LANGUAGE="JavaScript">
2 <!--
3 function dwn(s)
4 {
5 document.write(s+'<br/>');
6 }
7
8 //定义一个Collection类型
9 function Collection(size)
10 {
11 this.size = function(){return size}; //公有方法,可以被继承
12 }
13
14 //定义一个_Collection类型
15 function _Collection(_size)
16 {
17 this._size = function(){return _size}; //公有方法,可以被继承
18 }
19
20 Collection.prototype.isEmpty = function() //静态方法,不能被继承
21 {
22 return this.size() == 0;
23 }
24
25 //定义一个ArrayList类型,它“继承”Colleciton类型
26 function ArrayList()
27 {
28 var m_elements = []; //私有成员,不能被继承
29 m_elements = Array.apply(m_elements,arguments);
30
31 //ArrayList类型继承Colleciton
32 this.base = Collection;
33 this.base.call(this,m_elements.length);
34
35 this.base = _Collection; //可以实现多态继承
36 this.base.call(this,m_elements.length);
37
38 this.add = function()
39 {
40 return m_elements.push.apply(m_elements,arguments);
41 }
42
43 this.toArray = function()
44 {
45 return m_elements;
46 }
47 }
48
49 ArrayList.prototype.toString = function()
50 {
51 return this.toArray().toString();
52 }
53
54 //定义一个SortedList类型,它继承ArrayList类型
55 function SortedList()
56 {
57 //SortedList类型继承ArrayList
58 this.base = ArrayList;
59 this.base.apply(this,arguments);
60
61 this.sort = function()
62 {
63 var arr = this.toArray();
64 arr.sort.apply(arr,arguments);
65 }
66 }
67
68 //构造一个ArrayList
69 var a = new ArrayList(1,2,3);
70 dwn(a); //1,2,3
71 dwn(a.size()); //3 a从Collection继承了size()方法
72 dwn(a.isEmpty); //undefined 但是a没有继承到isEmpty()方法
73
74 dwn(a._size()); //3 可以实现多态继承
75
76 //构造一个SortedList
77 var b = new SortedList(3,1,2);
78 dwn(b.toArray());
79 b.add(4,0); //b 从ArrayList继承了add()方法
80 dwn(b.toArray()); //b从ArrayList继承了toArray()方法
81 b.sort(); //b自己实现sort()方法
82 dwn(b.toArray());
83 dwn(b);
84 dwn(b.size()); //b从Collection继承了size()方法
85 //-->
86 </SCRIPT>
2、原型继承法:
JavaScript是一种基于原型的语言。
要了解什么是“原型继承法”,先了解一下prototype的特性:prototype的最大特性是能够让对象实例共享原型对象的属性,因此如果把某个对
象作为一个类型的原型,那么我们说这个类型的所有实例都一这个对象为原型。这个时候,实际上这个对象的类型也可以作为那些以这个对象为原型的实例的类型。
假如:Point类的对象作为Point2D类型的原型(Point2D.prototype = new
Point(2)),那么说Point2D的所有实例都是以Point类的对象为原型。此时,实际上Point类就可以作为Point2D类型的对象的类
型(相当于Point2D类型“继承”了Point类型)。
见例:
1 <SCRIPT LANGUAGE="JavaScript">
2 <!--
3 function dwn(s)
4 {
5 document.write(s+"<br/>");
6 }
7
8 function Point(dimension) //定义一个Point类
9 {
10 this.dimension = dimension;
11 }
12
13 Point.prototype.distance = function() //静态方法,可以被继承
14 {
15 return this.dimension*2;
16 }
17
18 function Point2D(x,y) //定义一个Point2D类
19 {
20 this.x = x;
21 this.y = y;
22 }
23
24 Point2D.prototype = new Point(2); //运行“原型继承法”使Point2D继承Point
25
26 function Point3D(x,y,z) //定义Point3D类
27 {
28 this.x = x;
29 this.y = y;
30 this.z = z;
31 }
32
33 Point3D.prototype = new Point(3); //Point3D继承Point类
34
35 var p2 = new Point2D(1,2); //构造一个Point2D对象
36
37 var p3 = new Point3D(1,2,3); //构造一个Point3D对象
38
39 dwn(p2.dimension); //2
40 dwn(p3.dimension); //3
41 dwn(p2.distance()); //4 可以继承静态方法
42 dwn(p3.distance()); //6 可以继承静态方法
43
44 dwn(p2 instanceof Point2D); //p2是Point2D对象
45 dwn(p2 instanceof Point); //Point2D继承Point,p2是Point对象
46
47 dwn(p3 instanceof Point3D); //p3是Point3D对象
48 dwn(p3 instanceof Point); //Point3D继承Point,p3是Point对象
49
50 //-->
51 </SCRIPT>
3、实例继承法
构造继承法和原型继承法各有各的缺点,如:
构造继承法没有办法继承类型的静态方法,因此它无法很好的继承JavaScript的核心对象。
原型继承法虽然可以继承静态方法,但是依然无法很好地继承核心对象中的不可枚举方法。
其中,javascript核心对象包括:
Array 表述数组。
Boolean 表述布尔值。
Date 表述日期。
Function 指定了一个可编译为函数的字符串 JavaScript 代码。
Math 提供了基本的数学常量和函数;如其 PI 属性包含了π的值。
Number 表述实数数值。
Object 包含了由所有 JavaScript 对象共享的基本功能。
RegExp 表述了一个正则表达式;同时包含了由所有正则表达式对象的共享的静态属性。
String 表述了一个 JavaScript 字符串。
(1)构造继承法的局限性:
1 <SCRIPT LANGUAGE="JavaScript">
2 <!--
3 function MyDate()
4 {
5 this.base = Date;
6 this.base.apply(this,arguments);
7 }
8
9 var date = new MyDate();
10 alert(date.toGMTSring()); //对象不支持此方法或属性
11 //核心对象(Date)的某些方法不能被构造继承,原因是核心对象并不像我们自定义的一般对象那样在构造函数里进行赋值或初始化操作。
12 //-->
(2)原型继承的局限性
1 <SCRIPT LANGUAGE="JavaScript">
2 <!--
3 function MyDate()
4 {
5
6 }
7 MyDate.prototype = new Date();
8 var date = new MyDate();
9 alert(date.toGMTSring()); //'[object]不是日期对象'
10 //-->
11 </SCRIPT>
以上说明了“构造继承法”和“原型继承法”的局限性(局限之一:不能很好的继承核心对象),下面介绍如何用实例继承法来继承核心对象。
在介绍之前首先了解以下关于构造函数:
构造函数通常没有返回值,它们只是初始化由this值传递进来的对象,并且什么也不返回。如果函数有返回值,被返回的对象就成了new表达式的值。
1 <SCRIPT LANGUAGE="JavaScript">
2 <!--
3 function dwn(s)
4 {
5 document.write(s+'<br/>');
6 }
7 function MyDate()
8 {
9 var instance = new Date(); //instance是一个新创建的日期对象
10 instance.printDate = function() //对日期对象instance扩展printDate()方法
11 {
12 dwn(instance.toLocaleString());
13 }
14 return instance; //将instance作为构造函数的返回值返回
15 }
16
17 var date = new MyDate();
18 dwn(date.toGMTString());
19 date.printDate();
20 dwn(date instanceof MyDate); //false
21 dwn(date instanceof Date); //true
22 //对象的构造函数将会是实际构造的对象的构造函数(new Date()),而不是类型本身的构造函数(new MyDate())
23 //-->
24 </SCRIPT>
4、拷贝继承法
拷贝继承法是通过对象属性的拷贝来实现继承。
1 <script language="JavaScript">
2 function Point(dimension)
3 {
4 this.dimension = dimension;
5 }
6
7 var Point2D = function(x,y)
8 {
9 this.x = x;
10 this.y = y;
11 }
12
13 Point2D.extend = function()
14 {
15 var p = new Point(2);
16 for(var each in p) //将对象的属性进行一对一的复制。
17 {
18 //this[each] = p[each];
19 this.prototype[each] = p[each];
20 }
21 }
22 Point2D.extend();
23 //alert(Point2D.dimension);
24 alert(Point2D.prototype.dimension);
25 </script>
Ⅳ js中继承怎么理解,为什么要用js继承
js中继承跟java中的继承不太一样,一般通过call()和apply()两种方式完成,js中的继承是以复制的形式完成的,复制一个父对象,而不像java中直接继承父对象,还有通过原型的方式完成继承,也有弊端,总之js中的继承只是形式上的对面向对象语言的一种模仿,本质上不是继承,但用起来效果是一样的
至于为什么要继承:通常在一般的项目里不需要,因为应用简单,但你要用纯js做一些复杂的工具或框架系统就要用到了,比如webgis、或者js框架如jquery、ext什么的,不然一个几千行代码的框架不用继承得写几万行,甚至还无法维护