1.JS本身是基于面向对象开发的编程语言
类:封装、继承、多态
- 1.封装:类也是一个函数,把实现一个功能的代码进行封装,以此实现“低耦合高内聚”
- 2.多态:重载、重写
- 2.1 重写:子类重写父类上的方法(伴随着继承运行的)
- 2.2 重载:相同的方法,由于参数或者返回值不同,具备了不同的功能(JS中不具备严格意义上的重载,JS中的重载:同一个方法内,根据传参不同实现不同的功能)
- 3.继承:子类继承父类中的方法
2.重载
-
1.后台语言执行顺序
public void fn(int x,init y){ } public void fn(int x){ } //执行第一个FN fn(10,20); // 执行第二个FN fn(10); //报错 fn('张三'); -
2.js语言不存在严格意义上的重载
function fn(x, y) { } function fn(x) { } //执行第二个FN fn(10, 20); //执行第二个FN fn(10); -
3.JS传参y===undefined,y不存在做什么事情
function fn(x, y) { if(y===undefined){ // ...y=0; return; } // .... } //y===undefined,y不存在做什么事情 fn(10); fn(10, 20);
3.继承
- 1.在JS语言中,它的继承和其它编程语言还是不太一样的
- 2.继承的目的:让子类的实例同时也具备父类中私有的属性和公共的方法
1.JS中第一种继承方案:原型继承(让子类的原型等于父类的实例即可)
-
1.子类的实例,能够用子类私有的和原型上公有的
-
2.父类的实例,可以使用父类私有和原型上公有的
-
原型继承的特点:
-
1.父类中私有和共有的属性方法,最后都变为了类实例的共有的
-
2.和其他语言不同的是原型继承并不会把父类的属性方法‘拷贝’给子类,而是让子类实例基于__proto__原型链找到自己定义的属性和方法指向/查找方式的
-
3.C1__proto__.xxx=xxx修改子类原型(原有父类的一个实例)中的内容,内容被修改后,对子类的类其它实例有影响,但是对父类的实例不会有影响
-
4.C1__proto__.proto.xxx=xxx直接修改的是父类原型,这样不仅会影响其它父类的实例,也影响写子类的实例
function Parent() { this.x = 100; } Parent.prototype.getX = function getX() { return this.x; }; function Child() { this.y = 200; } //让子类的实例同时也具备父类中私有的属性和公共的方法 Child.prototype = new Parent; //=>原型继承 Child.prototype.getY = function getY() { return this.y; }; let c1 = new Child; console.log(c1);
-
2.JS中第二种继承方式:CALL继承(只能继承父类中私有的,不能继承父类中公共的)
//C1能用x和getX
function Parent() {
this.x = 100;
}
Parent.prototype.getX = function getX() {
return this.x;
};
function Child() {
// 在子类构造函数中,把父类当做普通方法执行(没有父类实例,
//父类原型上的那些东西也就和它没关系了)
// this -> Child的实例c1
// this.x=100 相当于强制给c1这个实例设置一个私有的属性x,
//属性值100,相当于让子类的实例继承了父类的私有的属性,
//并且也变为了子类私有的属性 “拷贝式”
Parent.call(this);
this.y = 200;
}
Child.prototype.getY = function getY() {
return this.y;
};
let c1 = new Child;
console.log(c1);
3.JS中第三种继承:寄生组合式继承(CALL继承 + 另类原型继承)
//C1能用x和getX
function Parent() {
this.x = 100;
}
Parent.prototype.getX = function getX() {
return this.x;
};
function Child() {
//1.改变this为parent
Parent.call(this);
this.y = 200;
}
//2.让子类的原型等于父类的原型
Child.prototype = Object.create(Parent.prototype);
// 3.破坏了原型,自己创建了原型,所有手动加coustructor保证原型的完整
Child.prototype.constructor = Child;
Child.prototype.getY = function getY() {
return this.y;
};
let c1 = new Child;
console.log(c1);
// 创建一个空对象,让其原型链指向obj
let obj = {
xxx: 'xxx'
};
console.log(Object.create(obj));
4.ES6中的类和继承
//C1能用x和getX
class Parent {
constructor() {
this.x = 100;
}
//1.类似原生 Parent.prototype.getX=function...
getX() {
return this.x;
}
}
// 2.继承: extends Parent(类似于寄生组合继承)
// 3.注意:继承后一定要在CONSTRUCTOR第一行加上SUPER
class Child extends Parent {
constructor() {
//=>4.super();类似于我们之前的CALL继承
//super(100,200):
//相当于把Parent中的constructor执行,传递了100和200
super();
this.y = 200;
}
getY() {
return this.y;
}
}
let c1 = new Child;
console.log(c1);
// Child();
//=>Uncaught TypeError: Class constructor Child cannot be invoked without 'new'
//ES6中创建的就是类,不能当做普通函数执行,只能new执行