面向对象编程有三个特色: 继承,封装,多态编程
ES6以前的继承,通常就是构造函数的继承。ES6以后,通常就是类的继承函数
分为两部分:this
1. 实例方法和属性继承spa
在子类构造函数中调用父类构造函数prototype
function Child() { Father.call(this); }
2. 原型属性和方法继承code
Child.prototype = Object.create(Father.prototype); Child.prototype.constructor = Child; // 构造函数的prototype赋值,函数会改变构造函数的指向
子类的实例this的生成基于父类的实例,因此必须先调用super(),获取父类实例。以后才能使用this。对象
class Child extends Father{ constructor(props) { super(props); // =Father.prototype.constructor.call(this,props) } } // super的用法: 1)做为父类构造函数,只能用在构造函数中 2)做为原型对象,在普通函数中:super.xxx(); super至关于父类的原型对象(super.prototype.xxx.call(this)),里面的this指向子类实例。 取不到子类的实例上面的属性和方法!! 3)做为父类,在静态方法中使用super,至关于父类,里面的this指向子类。
类的继承的实现原理:blog
Object.setPrototypeOf(Child, Father); Object.serPrototypeOf(Child.prototype, Father.prototype); // 即两条原型链以下 Child._proto_ = Father; Child.prototype._proto_ = Father.prototype;
ES6以前,即一个构造函数继承多个构造函数。继承
function Child() { Father1.call(this); Father2.call(this); } Child.prototype = Object.create(Father1.prototype); Object.assign(Child.prototype, Father2.prototype); Object.prototype.constructor = Child;
function mix(...mixins) { class Mix { constructor() { for (let mixin of mixins) { copyProperties(this, new mixin()); // 拷贝实例属性 } } } for (let mixin of mixins) { copyProperties(Mix, mixin); // 拷贝静态属性 copyProperties(Mix.prototype, mixin.prototype); // 拷贝原型属性 } return Mix; } function copyProperties(target, source) { for (let key of Reflect.ownKeys(source)) { if ( key !== 'constructor' && key !== 'prototype' && key !== 'name' ) { let desc = Object.getOwnPropertyDescriptor(source, key); Object.defineProperty(target, key, desc); } } }
ES5中没有模块的概念,能够模拟实现将代码封装成模块。接口
为了避免污染全局变量,不暴露内部属性,使用IIFE进行封装,return须要暴露的接口。
(function(){ var _prop = ""; function test(){}; return { a: test } })();
若是想和其余模块或者全局变量交互,能够经过IIFE的参数传入
这样能够清晰的了解交互内容和依赖。
ES6中出现了"模块"的概念。type="module";
模块经过import和export实现输入输出。