了解过面向对象的同窗应该都知道,面向对象三个基本特征是:封装、继承、多态,可是对于这三个词具体可能不太了解。对于前端来说接触最多的可能就是封装
与继承
,对于多态来讲可能就不是那么了解了。前端
封装
在说封装之先了解一下封装究竟是什么?java
什么是封装
封装:将对象运行所需的资源封装在程序对象中——基本上,是方法和数据。对象是“公布其接口”。其余附加到这些接口上的对象不须要关心对象实现的方法便可使用这个对象。这个概念就是“不要告诉我你是怎么作的,只要作就能够了。”对象能够看做是一个自我包含的原子。对象接口包括了公共的方法和初始化数据。(节选自百度百科)编程
我对于封装的理解,可能还有一个步骤就是抽离
,首先你要清楚在一个对代码中你应该抽离那些属性方法,有了这些为基础才能更好的作好封装。模块化
封装无非就是其属性和方法封装。函数
class Employees { constructor(name,age){ this.name = name; this.age = age; } getInfo(){ let {name,age} = this; return {name,age}; } static seyHi(){ console.log("Hi"); } } let lisi = new Employees("Aaron",18); lisi.seyHi(); // lisi.seyHi is not a function lisi.getInfo(); // {name: "Aaron", age: 18} Employees.seyHi(); // Hi
在Employees
中抽出的公共属性有name
,age
,公共方法有getInfo
,seyHi
,然而getInfo
与seyHi
所不一样的是seyHi
使用了static
修饰符,改变其为静态方法,seyHi
只属于Employees
这个类。然而getInfo
方法则是属于实例的。this
这里使用了static
对seyHi
方法对其进行了访问权限的封装。指针
再举一个例子。code
Promise.then() // Promise.then is not a function let p1 = new Promise(() => {}) p1.then(); // Promise {<pending>} Promise.all([1]); // Promise {<resolved>: Array(1)}
从上面的代码中能够看出Promise
也使用了static
对其方法的访问权限进行了封装。对象
继承
继承:说到继承并不太陌生,继承可使得子类具备父类的各类的公有属性
和公有方法
。而不须要再次编写相同的代码。在令子类别继承父类别的同时,能够从新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其得到与父类别不一样的功能。(节选自百度百科)继承
子类继承父类后,子类具备父类属性和方法,然而也一样具有本身所独有的属性和方法,也就是说,子类的功能要比父类多或相同,不会比父类少。
class Employees { constructor(name){ this.name = name; } getName(){ console.log(this.name) } static seyHi(){ console.log("Hi"); } } class Java extends Employees{ constructor(name){ super(name); } work(){ console.log("作后台工做"); } } let java = new Java("Aaron"); java.getName(); java.work(); // java.seyHi(); // java.seyHi is not a function
从上面的例子能够看出继承不会继承父类的静态方法,只会继承父类的公有属性与方法。这一点须要注意。
子类继承以后既拥有了getName
方法,一样也拥有本身的worker
方法。
多态
多态:按字面的意思就是“多种状态”,容许将子类类型的指针赋值给父类类型的指针。(节选自百度百科)
说白了多态就是相同的事物,一个接口,多种实现,同时在最初的程序设定时,有可能会根据程序需求的不一样,而不肯定哪一个函数实现,经过多态不须要修改源代码,就能够实现一个接口多种解决方案。
多态的表现形式重写与重载。
什么是重写
重写:子类可继承父类中的方法,而不须要从新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想做必定的修改,这就须要采用方法的重写。方法重写又称方法覆盖。(节选自百度百科)
class Employees { constructor(name){ this.name = name; } seyHello(){ console.log("Hello") } getName(){ console.log(this.name); } } class Java extends Employees{ constructor(name){ super(name); } seyHello(){ console.log(`Hello,个人名字是${this.name},我是作Java工做的。`) } } const employees = new Employees("Aaron"); const java = new Java("Leo"); employees.seyHello(); // Hello java.seyHello(); // Hello,个人名字是Leo,我是作Java工做的。 employees.getName(); // Aaron java.getName(); // Leo
经过上面的代码能够看出Java
继承了Employees
,然而子类与父类中都存在seyHello
方法,为了知足不一样的需求子类继承父类以后重写了seyHello
方法。因此在调用的时候会获得不一样的结果。既然子类继承了父类,子类也一样拥有父类的getName
方法。
什么是重载
重载就是函数或者方法有相同的名称,可是参数列表不相同的情形,这样的同名不一样参数的函数或者方法之间,互相称之为重载函数或者方法。(节选自百度百科)
class Employees { constructor(arg){ let obj = null; switch(typeof arg) { case "string": obj = new StringEmployees(arg); break; case "object": obj = new ObjEmployees(ObjEmployees); break; case "number": obj = new NumberEmployees(ObjEmployees); break; } return obj; } } class ObjEmployees { constructor(arg){ console.log("ObjEmployees") } } class StringEmployees { constructor(arg){ console.log("StringEmployees") } } class NumberEmployees { constructor(arg){ console.log("NumberEmployees") } } new Employees({}) // ObjEmployees new Employees("123456") // StringEmployees new Employees(987654) // NumberEmployees
由于JavaScript是没有重载的概念的因此要本身编写逻辑完成重载。
在上面的代码中定义了Employees
,ObjEmployees
,StringEmployees
,NumberEmployees
类,在实例化Employees
的时候在constructor
里面进行了判断,根据参数的不一样返回不一样的对应的类。
这样完成了一个简单的类重载。
总结
在编程的是多多运用这个写思想对其编程时颇有用的,可以使你的代码达到高复用以及可维护。