博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript 继承父类方法的正确姿势
阅读量:3915 次
发布时间:2019-05-23

本文共 3801 字,大约阅读时间需要 12 分钟。

JavaScript 继承父类方法的正确姿势

不想看前期的介绍可以直接划到最下面看总结和正确姿势,跳过原因的讲解。

初学 js ,总是喜欢把方法直接定义在对象内部,类似于 Java 那样。

下面定义一个简单 js 对象。

function Person() {    var locVal = '冲冲冲';    this.info = function () {        return locVal;    }}var p = new Person();var val = p.info();alert(val);

执行结果:

    

但是这样定义会产生问题,生成闭包,而且当你定义多个对象时重复调用 info 方法时,会重复生成 info 函数,就会造成系统内存泄漏,从而引起性能下降。

具体有关闭包的有关内容可以参考这篇博客:

那么我们要怎么解决这个问题呢?

我们可以通过 js 提供的 prototype 属性来解决这个问题。

function Person(name,age) {    this.name=name;    this.age=age;    this.info = function () {        document.write("姓名:" + this.name + "
"); document.write("年龄:" + this.age + "
"); }}var p1 = new Person('zkm',20);p1.info();Person.prototype.walk = function () { document.write(this.name + "正在慢慢溜达...
");} document.write('

');var p2 = new Person('ccc',30);p2.info();document.write('

');p2.walk();p1.walk();

执行结果:

    

在这里我们使用了 prototype 属性为 Person 类添加了一个属性,与其说是添加,不如说是销毁了原来的 Person 类,js 又重新创建了一个新的包含 walk 方法的 Person 类!而原来的 Person 类将不复存在。

这样做的效果,在各自调用 walk 方法时只会生成一次 ,不会产生副作用。

回到标题,解决了这个问题,我们要怎么继承父类的方法呢?我们一步一步来。

js 并不能实现真正的继承,为了解决这种问题,JavaScript提供了prototype 属性,来实现伪继承。

JavaScript 类的 prototype 属性代表了该类的原型对象。

在默认情况下,JavaScript 类的 prototype 属性值是一个 Object 对象,将 JavaScript 类的 prototype 设为父类对象 ,可实现 JavaScript 的继承,即原型链方法

function Person(name, age) {    this.name = name;    this.age = age;}Person.prototype.sayHello = function () {    console.log(this.name + "向您打招呼!");}var per = new Person("zkm",20);per.sayHello();function Student(grade) {    this.grade=grade;}Student.prototype = new Person('ccc',25);Student.prototype.intro = function () {    console.log("%s是一名学生,读%d年级",this.name,this.grade);}var stu = new Student(5);stu.name = "孙悟空";console.log(stu instanceof Student);console.log(stu instanceof Person);stu.sayHello();stu.intro();

解释代码:

    首先我们定义了一个 Person 类,有两个属性实例 name,age,通过 prototype 属性为 Person 类添加了 sayHello 方法。

    然后我们又定义了一个 Student 类,有一个属性实例 grade,我们想要它去继承 Person 类。

    JavaScript 类的 prototype 属性代表了该类的原型对象。

    所以  Student.prototype = new Person('ccc',25); ,Student 类的原型就是 Person 类,这样它就获得了 Person 类的属性和方法。

执行结果:

    

    我们能看到 stu 对象既属于 Student 也属于 Person。

    这样我们就成功继承了父类,但是这种做法有一种缺点,就是从父类继承过来的实例属性我们必须为它赋值,有多少就得赋多少个值,这样在创建多个对象时,就很麻烦,所以这也不是最好的方法,在介绍最正确的方法之前,我们还得了解另一种继承的方法。

构造器实现伪继承(对象冒充)

直接上代码:

//person类function Person(name, age) {    this.name = name;    this.age = age;    this.sayHello = function () {        console.log(this.name + "向您打招呼!");    }}var per = new Person("zkm",20);per.sayHello();//学生类function Student(name ,age ,grade) {    this.inherit = Person;//调用person类的构造方法,赋给实例变量    this.inherit(name,age);    this.grade=grade;}Student.prototype.intro = function () {    console.log("%s是一名学生,读%d年级",this.name,this.grade);}var stu = new Student("孙悟空",20,5);console.log(stu instanceof Student);console.log(stu instanceof Person); //false,伪继承stu.sayHello();stu.intro();

细心的小伙伴们已经发现了 Person 的 sayHello 方法又移到了里面。构造器继承,只会继承父类构造器里面的内容,并不会继承 prototype 后加的属性或方法。

这里可以把 子类 Student  构造器内的  this.inherit = Person; 和 this.inherit(name,age); 

替换成  Person.call(this,name,age) 

总结:(标准的 js 继承父类写法)

  • 不要在构造体中创建方法

  • 要为对象添加方法时,通过在外面 对象.prototype.方法名 = function(参数){方法体},来添加

  • 通过原型链的方式把父类所有的属性和方法继承过来

  • 为解决原型链的属性赋值问题,再通过构造器继承即对象冒充,再通过call和apply来把属性赋过来,就不用一个个赋值了

正确姿势:

//动物类function animal(sex, age) {    this.sex=sex;    this.age=age;}animal.prototype.info = function () {    console.log("名字叫%s,年龄是%d,性别是%s",this.name,this.age,this.sex);}//狗类function Dog(sex,age,name) {    this.name=name;    animal.call(this,sex,age);}Dog.prototype = new animal();Dog.prototype.bark = function () {    document.write("wangwangwang
");}//猫类function Cat(sex,age,name) { this.name=name; animal.call(this,sex,age);}Cat.prototype = new animal();Cat.prototype.bark = function () { document.write("miaomiaomiao
");}var dog = new Dog("男",2,"旺财");dog.info();dog.bark();var cat = new Cat("女",3,"喵喵");cat.info();cat.bark();

 

转载地址:http://qwprn.baihongyu.com/

你可能感兴趣的文章
Python supervisor
查看>>
dict & set
查看>>
Common Multiple and Least Common Multiple(LCM)
查看>>
大数据处理
查看>>
Difference Between Hard & Soft Links
查看>>
Linux Hard link and Symbolic link
查看>>
redis brief intro
查看>>
mongo db brief intro
查看>>
Kafka basic intro
查看>>
Python multiprocessing
查看>>
Python urlib vs urlib2
查看>>
Python Lib Queue.py
查看>>
count lines in a file - wc & nl
查看>>
需要注意的食物
查看>>
Nginx upstream schedule strategy
查看>>
Nginx Basic Config
查看>>
Nginx Load Balancer Config
查看>>
Nginx config hight throughput
查看>>
mysql max_connection config
查看>>
Python improve performance
查看>>