面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。对象指的是类的集合。类是指具有一类相同特征事物的抽象概念。对象是指具体某一个实例,唯一某一个个体。
在JavaScript中之前是没有类这个概念的,但是ECMA6中将类的概念加回来了。今天,我们一起来了解一下面向对象的继承、封装、多态。首先先看一下封装。
封装
封装就是把客观的事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的信息隐藏。隐藏实现细节,使得代码模块化。
封装一个构造函数:添加属性、添加方法、通过prototype原型(每一个函数都拥有一个prototype原型)
function Person(name, sex){
//this = new Object(); 原料操作
//添加属性
this.name = name;
this.sex = sex;
//return this; 出厂操作
}
//通过原型给该构造函数添加方法
Person.prototype.showName = function(){
alert("我的名字叫" + this.name);
}
Person.prototype.showSex = function(){
alert("我是" + this.sex + "的");
}
var p1 = new Person("钢铁侠", "男");
p1.showName(); //我的名字叫钢铁侠
p1.showSex(); //我是男的
var p2 = new Person("黑寡妇", "女");
p2.showName(); //我的名字叫黑寡妇
p2.showSex(); //我是女的
alert(p1.showName == p2.showName); //true
继承
继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。
1、首先是封装构造函数
function Person(name, sex){
// 添加属性
this.name = name;
this.sex = sex;
}
2、然后是通过原型给该构造函数添加方法。
Person.prototype.showName = function(){
alert("我的名字叫" + this.name);
}
Person.prototype.showSex = function(){
alert("我的性别是" + this.sex);
}
3、之后是在继承父级的基础上创建一个新的函数。
此处采用了三种方式继承父级的属性,三种方式可自由选择。
// 继承于Person,创建一个Worker构造函数
function Worker(name, sex, job){
// 继承属性
// 构造函数的伪装
Person.call(this, name, sex);
// Person.apply(this, [name, sex]);
// Person.bind(this)(name, sex);
// 拓展自己的属性
this.job = job;
}
4、然后对父级的方法进行继承
此处采用了三种方法来继承父级的方法,可根据个人喜好进行选择。
// 继承Person方法
// 1、原型链
/*for(var i in Person.prototype){
Worker.prototype[i] = Person.prototype[i];
}*/
// 2、Object.create()
// Worker.prototype = Object.create(Person.prototype);
// 3、直接调用父级的构造函数,进行继承
Worker.prototype = new Person();
5、之后,添加自己的方法。
// 添加自己的方法
Worker.prototype.showJob = function(){
alert("我的工作是" + this.job);
}
6、最后,调用。
var w1 = new Worker("orange", "女", "程序猿");
w1.showName();
w1.showSex();
w1.showJob();
var p1 = new Person("panda", "男");
p1.showName();
p1.showSex();
alert(p1.showJob); //undefined
继承的【拓展】
1、构造函数 prototype原型对象
2、构造函数构造的对象 __proto__ 属性 指向构造函数的prototype原型。
var w1 = new Worker("小明", "男", "程序猿");
// alert(w1.__proto__ == Worker.prototype); //true
var p1 = new Person("blue", "男");
// alert(p1.__proto__ == Person.prototype); //true
alert(p1.__proto__ == w1.__proto__); //false
alert(p1.__proto__ == Worker.prototype); //false
说完了封装和继承,我们最后一起看一下什么是多态
多态
不同类的对象对同一消息做出响应。同一消息可以根据发送对象的不同而采用多种不同的行为方式。
function Person(name, sex){
this.name = name;
this.sex = sex;
}
Person.prototype.showName = function(){
alert("我的名字叫" + this.name);
}
Person.prototype.showSex = function(){
alert("我是" + this.sex + "的");
}
//继承于Person,创建一个Worker构造函数
function Worker(name, sex, job){
Person.call(this, name, sex);
this.job = job;
}
//继承Person方法
//原型链
for(var funcName in Person.prototype){
Worker.prototype[funcName] = Person.prototype[funcName];
}
/*【注】重写从父一级继承的函数,那么在子一级上,重写的函数会覆盖继承的函数,
不会影响父一级的函数。这叫做多态。*/
Worker.prototype.showName = function(){
alert("大家好,Worker的介绍自己的名字是" + this.name);
}
//添加自己的方法
Worker.prototype.showJob = function(){
alert("我的工作是" + this.job);
}
var p1 = new Person("blue", "男");
var w1 = new Worker("red", "女", "会计");
p1.showName();
w1.showName();