一、类class
在es6中,可以使用class关键字声明一个类,之后以这个类来实例化对象。
类抽象了对象的公共部分,它泛指某一大类 对象特指某一个,通过实例化一个具体的对象
继承:子类可以继承父类的一些属性和方法
class Father{
constructor(x,y){
this.x = x;
this.y = y;
}
sum(){
console.log(this.x + this.y);
console.log(this.x)
}
say(){
return '我是爸爸'
}
}
class Son extends Father{
constructor(x,y){
super(x,y);//调用了父类中的构造函数,必须在子类this之前调用
this.x = x;
this.y = y;
}
say(){
console.log(super.say() + '的儿子')//super调用父类的普通函数
}
}
var son = new Son(1,2)
son.sum();
son.say();
1.类的constructor构造函数
类里面有个constructor函数,可以接收传递过来的参数,同时返回实例对象
constructor函数只要new生成实例时,就会自动调用这个函数,如果不写constructor这个函数,类也会自动生成这个函数。
类的共有属性放在constructor里面
类里面所有的函数不用写function;也不加,分割
2.extends 让子类继承父类
super关键字:可以调用父类的constructor(构造函数),也可以调用父类的普通函数。
子类在构造函数(constructor)中使用super,必须放在this前面(必须先调用父类的构造函数,再使用子类构造方法)
3.继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法。(就近原则)
4.在es6中类没有变量提升,所以必须先定义类,才能通过类实例化对象
类里面的共有属性和方法一定要加this
二、构造函数
构造函数是一种特殊的函数,主要用来初始化对象(也就是为对象成员变量赋值),它总与new一起使用。我们可以把对象中一些公共属性和方法抽取出来,然后封装到这个函数里面。
实例成员:(函数内部通过this添加的成员)只能通过实例化的方法来访问
静态成员:(在构造函数本身上添加的成员)静态成员只能通过构造函数来访问
new在执行时做了什么?
(1)在内存中创建一个新的空对象(2)让this指向这个新的对象
(3)执行构造函数里面的代码,给这个新对象添加属性和方法
(4)返回这个新对象(所以构造函数里不需要return)
function Star(uname,uage){
this.uname = uname;//实例成员
this.uage = uage;
this.sing = function(){
console.log('我唱歌')
}
}
var ldh = new Star('刘德华',20);
console.log(ldh.uname);
ldh.sing()//1.实例成员(函数内部通过this添加的成员)只能通过实例化的方法来访问
//Star.sing()//报错
Star.sex = '男';//2.静态成员(在构造函数本身上添加的成员)
console.log(ldh.sex)//undefined
console.log(Star.sex)//男 静态成员只能通过构造函数来访问
构造函数方法很好用,但是存在浪费内存的问题
构造函数中不变的方法在每次new一个实例的时候,都会在堆里面开辟一个空间。我们想让这个不变的方法只占一个空间,所以就有了构造函数原型。
三、构造函数原型prototype
JS规定每一个构造函数都有一个prototype属性,指向另一个对象。我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法。
四、es5继承与es6继承的区别
继承:子类可以继承父类的一些属性和方法
(1)Es5的继承实质是先创建子类的实例对象,然后再将父类的方法添加到this上(Father.call(this))。
Es6的继承实质是先创建父类的实例对象this,然后再用子类的构造函数修改this。
(2)Es5的继承通过构造函数和原型来实现
Es6通过class关键字定义类,类里面有构造方法,类之间通过关键字extends实现继承。子类必须在constructor方法中调用super方法,否则新建实例报错。因为子类没有自己的this对象,而是继承类父类的this对象,然后对其加工。如果不调用super方法,子类将得不到this对象。
五、es5定义一个类,并实现继承
组合继承
function Father(name,age){
this.name = name;
this.age = age;
}
Father.prototype.work = function(){//父亲的方法
console.log('父亲工作')
}
function Son(name,age){
Father.call(this,name,age)//继承父类的属性(在father中把this指向子构造函数的实例)
}
Son.prototype.study = function(){
console.log('孩子上学')
}
Son.prototype = new Father();//继承父类的方法(直接赋值,修改了儿子原型对象的constructor)
Son.prototype.constructor = Son;//把儿子的constructor修改回去
var son = new Son('小明',18);
console.log(son);
console.log(son.__proto__.constructor)
console.log(son instanceof Father);
寄生组合式继承
function Father(name,age){
this.name = name;
this.age = age
}
Father.prototype.work = function(){
console.log('父亲工作')
}
function Son(name,age){
Father.call(this,name,age);//继承父类的属性
}
Son.prototype.study = function(){
console.log('孩子上学')
}
Son.prototype = Object.create(Father.prototype);
//继承父类的方法:先创建了一个临时的构造函数,然后将父亲的原型对象作为这个构造函数的原型,最后返回临时类型的新实例
//然后让儿子的原型对象指向临时类型的新实例(这样就可以实现继承了)
Son.prototype.constructor = Son;
var son = new Son('aaa',23);
console.log(Son.prototype);
console.log(son.__proto__.constructor)
object.create相当于下面的create函数(不用写)
function create(obj) {
function F() {}//先创建了一个临时的构造函数
F.prototype = obj;//然后将传入的对象作为这个构造函数的原型
return new F();//返回了临时类型的新实例
}