JS自己是基于面向对象开发的编程语言:因此咱们学习JS主要就是学习类,以及类的实例,在学习类的原型上提供的方法;javascript
类:java
- 封装、继承、多态
//=> 在后台语言中,
public void fn(int x,init y){
}
public void fn(int x){
}
fn(10,20); 执行第一个FN
fn(10); 执行第二个FN
fn('小芝麻'); 报错
复制代码
function fn(x, y) {
}
function fn(x) {
}
fn(10, 20); 执行第二个FN
fn(10); 执行第二个FN
复制代码
function fn(x, y) {
if(y===undefined){
// ...
return;
}
// ....
}
fn(10);
fn(10, 20);
复制代码
这里想到了一个笑话:编程
A去医院检查,被查出是“类风湿性关节炎”
A:好郁闷,得了…
B:这个病注意点就行了啊
A:不行,由于咱们打算要孩子
B:你这个病和孩子有啥关系啊
….
10min A的脑子中 "类风湿性关节炎” => 类是继承的 复制代码
在生物学上的继承相似于:浏览器
父亲:基因
AAA BBB CCC
儿子:继承了父亲的基因(把父亲的部分基因,直接拷贝到自身上)
AAA BBB
儿子基因突变 AAB BBA,可是对父亲是没有影响的
复制代码
正常的后台语言中的继承,就是这种拷贝式的继承,可是咱们JS中的继承并非这种继承;bash
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);
复制代码
如今c1 能用的方法是:私有的 y 和公有的 getY方法,以及Object上的公有方法;服务器
因此咱们只要让子类的原型等于父类的实例便可编程语言
- Child.prototype = new Parent
__proto__
原型链找到本身定义的属性和方法“指向/查找”方式的c1.__proto__.xxx = xxx
修改子类原型(原有父类的一个实例)中的内容,内容被修改后,对子类的其余实例有影响,可是对父类的实例不会有影响函数
c1.__proto__.__proto__.xxx = xxx
直接修改的是父类原型,这样不只会影响其它父类的实例,也影响其余子类的实例学习
JS中的重写影响很大ui
function Parent() {
this.x = 100;
}
Parent.prototype.getX = function getX() {
return this.x;
};
function Child() {
// 在子类构造函数中,把父类当作普通方法执行(没有父类实例,父类原型上的那些东西也就和它不要紧了)
// this -> Child的实例c1
Parent.call(this); // this.x=100 至关于强制给c1这个实例设置一个私有的属性x,属性值100,至关于让子类的实例继承了父类的私有的属性,而且也变为了子类私有的属性 “拷贝式”
this.y = 200;
}
Child.prototype.getY = function getY() {
return this.y;
};
let c1 = new Child;
console.log(c1);
复制代码
parent(this)
这个 this
是 window
call
强制改变 this
的指向为 Child
中的 this
Parent.call(this)
this
是当前 Child
中的 this
至关于强制给实例设置了一个私有的属性,至关于让子类的实例继承了父类的私有的属性,而且也变为了子类私有的属性“拷贝式”
咱们满意的继承方式应该是:父类私有变为子类私有 父类公有变为子类公有
function Parent() {
this.x = 100;
}
Parent.prototype.getX = function getX() {
return this.x;
};
function Child() {
Parent.call(this);
this.y = 200;
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
Child.prototype.getY = function getY() {
return this.y;
};
let c1 = new Child;
console.log(c1);
复制代码
那如今咱们只要想办法让父类中公有的也能变成子类中公有的便可;
咱们刚才的原型继承,大致的实现了这个功能;
Child.prototype.__proto__ === Parent.prototype;
Child.prototype.__proto__ = Parent.prototype;
这样虽然能实现效果可是IE浏览器中不容许咱们操做__proto__
,那咱们有什么能够替换它呢?
// Object.create();建立一个空对象,让其原型链指向obj
let obj = {
xxx: 'xxx'
};
console.log(Object.create(obj));
复制代码
因此能够写成:Child.prototype = Object.create(Parent.prototype);
便可
constructor
属性,因此咱们本身手动加一个默认的;class Parent {
constructor() {
this.x = 100;
}
// Parent.prototype.getX=function...
getX() {
return this.x;
}
}
复制代码
// 继承: extends Parent(相似于寄生组合继承)
// 注意:继承后必定要在CONSTRUCTOR第一行加上SUPER
class Child extends Parent {
constructor() {
super(); //=>相似于咱们以前的CALL继承 super(100,200):至关于把Parent中的constructor执行,传递了100和200
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执行
复制代码