关于javascript:关于原型与继承

2次阅读

共计 2675 个字符,预计需要花费 7 分钟才能阅读完成。

原型

原型是 Javascript 中的继承的根底,Javascript 中的继承就是原型的继承。

构造函数

其实就是咱们平时写的函数,能够用 new 关键字来创立实例的,咱们称之为构造函数。

当申明一个函数时,浏览器会主动生成一个原型对象,贮存在内存之中。

function add() {let a = 1}
const f = new add()
// add() 就是一个构造函数
// f 就是构造函数 add() 的实例 

原型链

通过_proto_链接起来的链式关系就是原型链

原型链决定了 Javascript 的继承关系

当咱们查找一个属性时,查找机制如下:

  • 拜访对象属性,有则返回,没有就通过_proto_去它的原型对象外面找
  • 一层一层找直到找到 Object.prototype, 如果找到就返回,没有找到就返回 undefind,因为再往下找_proto_外面就是 null

继承

原型链继承

原型链继承通过批改子类的原型为父类的实例,从而达到子类能过拜访父类的原型上的属性和办法

function Parent() {this.name = 'nana'}
Parent.prototype.getName = function () {return this.name;}
function Child() {constructor()
}
Child.prototype = new Parent()
const child = new Child()
const child2 = new Child();
child.name = 'heaven'
child.getName(); // 'heaven'
child2.getName(); // 'heaven'
// 'nana'

长处:实现简略不便。
毛病:父类构造函数中的援用类型(数组 / 对象),会被所有子类实例共享,其中一个子类实例进行批改时,会导致其余所有子类实例这个值都会被扭转。

构造函数继承

通过批改父类构造函数 this 实现的继承。就是在子类构造函数中执行父类的构造函数,批改父类 this 为子类 this.

function Parent() {this.info = ['name','age','sex']
}
function Child() {Parent.call(this)
}
const child = new Child()
child.info.push('school')
const child2 = new Child()
console.log(child,'child'); // ['name', 'age', 'sex', 'school']
console.log(child2,'child2'); // ['name', 'age', 'sex']

长处:完满解决了下面原型链继承的毛病,其中一个子类实例属性值被批改不会影响其余子类。
毛病:办法都定义在构造函数中,每次都须要从新创立,比拟浪费资源。

组合继承

联合原型链继承和构造函数继承。

function Parent() {this.info = ['name','age','sex']
}
Parent.prototype.getName = function () {return this.info;}
function Child() {Parent.call(this)
  this.topic = 'fe';
}
Child.prototype = new Parent()
Child.prototype.constructor = Child
const child = new Child()
child.info.splice(0,1)
const child2 = new Child()
console.log(child,'child');
console.log(child2,'child');

长处:同时解决了构造函数援用类型的问题和防止了办法被创立屡次。
毛病:父类构造函数被调用了两次,同时子类实例以及子类原型对象上都会存在 info 属性。

寄生组合继承

在组合继承的根底上,解决了父类结构函数调用两次的问题。

function Parent() {this.info = ['name','age','sex']
}
Parent.prototype.getName = function () {return this.info;}
function Child() {Parent.call(this)
  this.topic = 'fe';
}
inherit(Child,Parent)
function inherit(child,parent) {let prototype = Object(parent.prototype)
  prototype.constructor = child
  child.prototype = prototype
}
function object(o) {function f() {}
  f.prototype = o;
  return new f()}
const child = new Child()
child.info.push('school')
const child2 = new Child()
console.log(child,'ll'); //['name', 'age', 'sex', 'school']
console.log(child2,'22'); //['name', 'age', 'sex']

长处:是目前为止最正当的实现继承的形式。
毛病:比较复杂。

ES6 继承

ES6 提供了 class 语法糖,同时提供了 extends 用于实现类的继承。这也是我的项目开发中举荐应用的形式。

class Ground{constructor(age){this.age = age;}
    lunch(){console.log('吃午饭');
    }
}
class Person extends Ground{constructor(name,age){super(age);
      this.name = name;
    }
    drink(){console.log('喝水');
    }
}
class Student extends Person{constructor(name,score,age){super(name,age);
      this.score = score;
    };
    info(){console.log(` 我是 ${this.name}, 年龄 ${this.age}, 分数 ${this.score}`);
    }
}
const student = new Student('张三',19,99)
student.info() // 我是张三, 年龄 99, 分数 19

参考

https://juejin.cn/post/684490…

https://zhuanlan.zhihu.com/p/…

正文完
 0