1、封装
隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。
JavaScript(JS)中ES6之前没有类的概念,封装定义类相当于定义函数,写法如下:
function Person (name,age,sex){ this.name = name; this.age = age; this.sex = sex; } Pserson.prototype = { constructor:Person, sayHello:function(){ console.log('hello'); } }
ES6中引入 class(类)这个概念,写法如下:
//定义类 class Person{ // 类的静态方法,相当于Person.test = function(){console.log("类的静态方法");} static test() { console.log("类的静态方法"); } //constructor构造函数 constructor(name,age){ console.log("调用构造函数"); this.name = name; this.age = age; } //类的一般方法,定义在实例对象的原型对象上,相当于Person.prototype.show = function(){console.log("this.name,this.age");} show(){ console.log(this.name,this.age); } }
2、继承
提高代码复用性;继承是多态的前提。JavaScript(JS)中ES6之前继承是通过prototype
(原型)实现,使父类中的属性和方法在子类实例的prototype
原型链上,不同于其他语言中的继承(其他语言的继承一般是继承拷贝,也就是子类继承父类,会把父类中的属性和方法拷贝一份到子类,供子类的实例调取使用),JavaScript(JS)中把父类的原型放到子类实例的原型链上的,实例想调取这些方法,是基于__proto__
原型链查找机制完成的。子类可以重写父类上的方法。但父类其他的实例也受到影响。父类中私有或者共有的属性方法都会变成子类的共有属性和方法
prototype
和__proto__
的区别:prototype
是函数才有的属性,而__proto__
是每个对象都有的属性。
写法如下:
//父类 function A(x) { this.x=x } A.prototype.getX=function(){ console.log(this.x) } //子类 function B(x) { this.y=y } //B的原型指向A的实例 B.prototype=new A() B.prototype.constructor=B B.prototype.getY = function(){ console.log(this.y) } let b1=new B(100) console.log(b1.y)//100 b1.getX()//undefined b1.getY()//100
ES6中可以使用extend(extends和super)实现继承,写法如下:
//es6中继承 class A { constructor(x){ this.x=x } getX(){ console.log(this.x) } } class B extends A { //子类只要继承父类,可以不写constructor,如写了就需要使用super调用指定的父类的构造函数。 //不写constructor 浏览器会自动默认创建constructor(...arg){} constructor(y) { //把父类当做普通方法执行,给方法传递参数,让方法中的this是子类的实例 super() this.y=y } getY(){ console.log(y) } }
3、多态
父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。JavaScript(JS)中ES6之前多态用法如下:
var makeSound = function(animal) { animal.sound(); } var Duck = function(){} Duck.prototype.sound = function() { console.log('duck') } var Chicken = function() {}; Chicken.prototype.sound = function() { console.log('chicken') } makeSound(new Chicken()); makeSound(new Duck());
ES6中多态写法如下:
class Animal{ eat(){ throw '"' + this.constructor.name + "'类没有eat()方法"; } } class Snake extends Animal{} class Dog extends Animal{ eat(){ console.log("dog eat"); } } class Cat extends Animal{ eat(){ console.log("cat eat"); } } var makeEat=function(animal){ animal.eat(); } makeEat(new Snake()); makeEat(new Dog()); makeEat(new Cat());