1.继承。
javascript中的继承是一个非常复杂的话题,比任何其他面向对象语言中的继承都复杂得多。在大多数其他面向对象语言中,继承一个类只需要一个关键字。与它们不同的是,为了继承javascript中的公共成员,需要采取一系列措施。此外,javascript是少数使用原型继承的语言之一。由于这种语言的灵活性,您可以使用标准的基于类的继承或者更微妙的原型继承。
2.为什么需要继承?
一般来说,在设计类时,我们希望减少重复代码,尽量减少对象之间的耦合。使用继承满足了前面设计原则的需要。有了这个机制,就可以在已有类的基础上进行设计,充分利用它们已有的方法,更容易修改设计。假设您需要几个类来拥有一个以特定方式输出类结构的toString()方法。当然,您可以通过复制和粘贴将定义toString()方法的代码添加到每个类中,但是如果您这样做了,那么每当您需要更改此方法的工作模式时,您将不得不在每个类中重复相同的修改。相反,如果您提供一个ToStringProvider类并让这些类继承这个类,那么toString方法只需要在一个地方声明。
让一个类从另一个类继承可能会导致强耦合,也就是说,一个类依赖于另一个类的内部实现。我们将讨论一些有助于避免这个问题的技术,包括为具有掺杂类的其他类提供方法的技术。
3.基于类的继承。
请看下面的代码:
脚本类型='text/javascript '函数Person(姓名、年龄){ this.name=namethis.age=年龄;} person . prototype . say=function(){ console . log(this . name ', this . age);}函数Student(no){ this . no=no;}/* * *学生原型指向Person *//span学生的对象。prototype=new person();var stu1=新学生(' 0001 ');Stu1.name='张三';stu 1 . age=' 11 ';console . log(stu 1 . no);stu 1 . say();/脚本输出:张三和11可以看到,学生成功整合了Person,拥有了Person的说法。核心代码其实就是一句student . prototype=new Person();下面说明了原理:
将Student.prototype指向newperson(),newperson的_proto_指向personprototype。这就完成了整个继承。
但是,这种方法有问题:
问题1:当父类有引用类型变量时,数据不一致。接下来,我们给Person添加一个爱好属性,它的类型是array。
脚本类型=' text/JavaScript'/* * *有问题。* 1.对于父类的构造函数,不能在Student的构造函数中传递参数。* 2.引用类型变量导致的数据不一致。*/函数人(姓名、年龄){this。name=namethis.age=年龄;this . affairs=[];} person . prototype . say=function(){ console . log(this . name ', this.age ', this . affairs);}函数Student(no){ this . no=no;} student . prototype=new Person();var stu1=新学生(' 0001 ');Stu1.name='张三';stu 1 . age=' 11 ';stu 1 . affairs . push(足球);stu 1 . say();var stu2=新学生(' 0002 ');Stu2.name='李四';stu 2 . age=' 12 ';stu 2 . affairs . push(' girl ');stu 2 . say();/脚本输出:张三,11岁,足球李四,12岁,足球,女生可以看出李四的爱好应该只有女生,但是上面的代码让所有对象共享了爱好属性。上面的继承模式还是有问题的:
2.在Student的构造方法中,不能使用New Student(“00001”,“张三”,12)。要创建对象并初始化名称和年龄属性,必须分配stu.name、stu.age。
要解决上述问题,请修改上述代码:
脚本类型='text/javascript '函数Person(姓名、年龄){ this.name=namethis.age=年龄;this . affairs=[];} person . prototype . say=function(){ console . log(this . name ', this.age ', this . affairs);}函数student(姓名、年龄、否){/* * *使用call方法,第一个参数为context*有点类似Java中super(姓名、年龄)的感觉*/Person.call(this,姓名、年龄);this.no=no} student . prototype=new Person();Var stu1=新生(' 0001 ','张三',11);stu 1 . affairs . push(足球);stu 1 . say();Var stu2=新生(' 0002 ','李思',12);stu 2 . affiliations . push('苍劲');stu 2 . affairs . push(篮球);stu 2 . say();/脚本输出:0001,张三,足球0002,李四,沧金,篮球在Student的构造方法中使用了Person.call(this,name,age),感觉像super (name,age)[call的第一个参数是context];并成功解决了共享引用属性的问题,完美。
4.基于原型链的继承。
脚本类型=' text/JavaScript'/* * *基于原型链的集成是所有对象。*存在问题:* 1。对于引用类型变量,数据不一致。*/var Person={name:' person ',age3360 0,hobies 3360[],say : function(){ console . log(this . name ',' this.age ',' this . affairs);} } ;var Student=clone(人);Student.no=student . SayHellO=function(){ console . log(this . name ' hello ');} var stu1=克隆(Student);stu1.name='张山';stu 1 . age=12;stu 1 . affairs . push(' Java ');stu 1 . say();var stu2=克隆(学生);stu 2 . name=' Lisi ';stu 2 . age=13;stu 2 . affairs . push(' Javascript ');stu 2 . say();/* * *返回执行obj * @ paramobj * @的原型对象,返回{ f } */function clone(obj){ var f=function(){ };f .原型=obj返回新的F();}/脚本输出:张山,12,javalisi,13,Java,JavaScript,可以看出也存在引用属性不一致的问题,而且整个操作都是基于对象的,给人不好的感觉。这里有一个图表来解释这个原理:
对象通过克隆函数不断返回一个新对象,原型执行传入的对象。整个继承过程其实就是_ prototype _不断指向形成一个链,所以叫做原型链。
好的,我已经介绍过了。集成js最好的方法是通过类继承,相对稳定。
以上是对传承知识点相关内容的介绍,希望对大家的学习有所帮助。