JavaScript面向对象(一)
面向对象程序设计(入门篇)
在程序员眼里面一切皆为对象,你能看的见摸的着的都算
如何给你的女朋友解释什么是面向对象编程?
周末午后,我正在愉快的玩着游戏,这个时候女朋友跑来了,拿着一本叫做《面向对象编程》的书来找我
问道:
什么是面向对象?难道是要面向我写代码么?
不是啦,这个面向对象的对象不是你这个对象
此时,我突然菊花一紧,感受到了一股莫名的杀气
什么?你还有其他对象?有我好看么?
什么是面向对象?
面向对象,英文我们叫Object Oriented,这是一种软件开发的方法(思路),与面向过程是对应的
女朋友突然说:
不要跟我飙英文,给我说清楚,不然今天没完。
我有点饿了,要不然你给我做饭吃把,然后我们边吃边聊
我现在就像听你说,要不我们直接点外卖把,别自己动手做饭了
其实对于吃饭这件事情,我们就可以分为面向对象吃饭和面向过程吃饭,亲自下厨就是面向过程,点外卖就是面向对象
在面向过程的吃饭中,我们想要填饱肚子,需要自己亲自下厨把饭做出来,那么我就需要想好吃什么,然后去买菜,洗菜,洗米,切菜,蒸饭,炒菜等等一系列的事情要做
function 做饭(){
指定菜单;
买菜;
洗菜;
西米;
蒸饭;
炒菜;
.........
}
那么,我们说跟点外卖相比,自己做饭有哪些缺点?肯定是麻烦撒
面向过程编程就是这样,由于想要完成做饭这个事情,需要自己定义超级多的方法,除此至外,还有很多问题可能出现,比如
我不想吃米饭,我想吃馒头
上次买的菜,还有剩的不需要去买菜
中午吃剩的菜,直接热一热就可以直接吃了
这次去的超市提供洗菜服务,不需要自己洗菜了
以上这些突发事件,在编程过程中叫做需求变更或者需求跟新,这种事情是必然会发生的
那么,如果出现新的需求怎么办?上面这种手动做饭的场景,就只能重新拼凑了
对于程序员来讲,需要通读代码,找出可以复用的方法,然后重新调用,不能复用的重写一个,时间久了,方法会越来越多,系统维护就越来越麻烦
面向对象
面向对象其实就是我们通过点外卖的方式来做饭,我们知道我们需要一顿饭,我们只需要打开外卖软件,在里面选择我们需要的菜品然后下单就可以了,我们不关心饭店做饭的过程,想吃什么点什么,家里突然来人了,拿我们再下个订单就好,不想吃米饭,想吃馒头,可以订单备注或者打电话给饭店说,让他们把米饭换成馒头【我们不关心你的实现过程,我只根据我的需求关注结果】
外卖软件.点餐(红烧肉,糖醋排骨,可乐).送达时间(一小时后).备注(可乐加冰)
所以,通过面向对象的方式做饭,就像上面的代码一样。
女朋友:
哦,我明白了,面向对象就是把本来可能需要自己做的事情交给别人去做?对于我来说,外卖软件就是个对象,我再面向它“做饭”,其实它帮我做
我说:
额,你的也对,也不对。在这个场景中我们确实可以把外卖软件当成是一个对象。其实,在面向对象编程中,抛弃了函数,想要实现一个功能不再是通过函数的叠加调用来实现,而是通过对象
对象就是对事物的一种抽象描述,现实世界中的事情,都可以用【数据】加【能力】来描述
比如我要描述一个人,【数据】可以是它的年龄,身高,体重,姓名,性别,【能力】可以说是它是做什么工作的,承担什么样的责任
描述一个外卖软件,【数据】就是它所包含的菜品,而【能力】它可以点餐
上面我们通过语义的角度理解了什么是面向对象
如果一个东西是一个对象,那么它应该具备以下几个特点
1、对象具备属性
属性就是用于描述当前对象的特征,可以理解成上面说的【数据】
2、对象具备方法
方法就是一个对象的功能,例如它可以做什么事情,可以理解成上面的【能力】
3、对象是可以继承的
父对象里面的某些方法或属性是可以在子对象中继续使用的
想一想: 为什么需要对象这个概念,如果没有对象怎么办?会有什么问题?
场景: 现在我虚妄讲小明和小芳的信息记录下来,怎么办?,分别记录他们的姓名,性别,年龄,爱好
var name1 = "小明";
var sex1 = "男";
var age1 = 20;
var hobby1 = "打游戏"
//以上是小明的信息
var name2 = "小芳";
var sex2 = "女";
var age2 = 18;
var hobby2 = "吃饭"
通过上面的代码,我们可以看到,我们如果说现在我想把班里所有的人信息记录下,这个时候就超级麻烦,我们需要定义超级多的变量
上面我们每四个变量才能够描述一个学生的信息,但是我们每次都定义变量,这样会很麻烦,在程序员眼中,我们的代码都应该要做到一个特点叫做**" 低耦合,高内聚 "**
高内聚可以理解成物以类聚,某些东西或事物如果具备相同的属性的时候,我们就应该把它归纳一类
如果没有对象的话,上面的东西就很难实现,所以我们迫切的需要一种集中形式的数据管理方式,而这种管理方式就是面向对象编程
对象的创建
对象的创建我们可以理解成对象的封装
通过键值对来创建对象
在JavaScript的对象里面,键(key)也叫对象的属性名,值(value)也叫对象的属性值,所以键值对的创建其实就是属性名于属性值的方式来创建对象
var 对象名 = {
属性名1:属性值1,
属性名2:属性值2,
//.......
}
我们现在已经知道了键值对的语法格式,那么我们把上面的学生信息通过对象的方式重构
var stu1 = {
name:"xiaoming",
sex:"nan",
age:18,
hobby:dayouxi
};
var stu2 = {
name:"xiaofang",
sex:"nv",
age:20,
hobby:"chifan"
}
上面的代码中,我们只定义了两个变量分别是stu1于stu2,但是他们都是对象,我们分别给两个对象给它添加了4个属性分别是
name,sex,age,hobby
这四个属性都是用于描述这两个对象的特征的
属性只是对象的一个特点,我们还可以有方法,怎么在对象里面创建方法
var stu1 = {
name:"xiaoming",
sex:"nan",
age:18,
hobby:dayouxi
sayHello:function(){
console.log("hello world");
}
};
如果我们想在方法里面拿到当前对象的属性,怎么办?
第一种
var stu1 = {
name:"xiaoming",
sex:"nan",
age:18,
hobby:dayouxi
sayHello:function(){
console.log(stu1.name);
}
};
但是这种写法有个缺点,它必须要借助对象来完成调用,那么如果对象名变了,那么就需要方法里面的对象名也需要一起改
第二种
var stu1 = {
name:"xiaoming",
sex:"nan",
age:18,
hobby:dayouxi
sayHello:function(){
console.log(this.name);
}
};
通过object去创建对象
除了上面的 {}
的键值对方式创建以外,我们还可以使用object来创建对象
var obj = new Object(); //相当于是赋值了一个{}
得到空对象直接怎么向内添加属性和方法
var obj = new Object();
obj.name = "zhangsan";
obj.sex = "nan";
obj.sayHello = function(){
}
在上面的两种对象的创建方式来看,我们会发生另外一个问题,这两种方式如果说创建多个同类型的对象的时候会超级麻烦,如果班上有100个学生,我们要把这个100个学生的姓名,性别,年龄,爱好以及sayHello方法都创建好,这样很麻烦
使用构造函数创建对象(重点!!!!!!!!!)
所有的构造函数在调用的时候都是使用 new
来进行调用,并且构造函数的命名一般都是首字母大写
//定义了一个普通的方法
function sayHello(){
return 123;
}
//通过常规方法调用
var a = sayHello() //返回123
//通过构造函数调用
var b = new sayHello() //返回一个对象
通过上面的代码我们可以得到,只要 new
一个函数就可以得到一个对象
语法格式:
var 对象名 = new 函数();
我们现在来自己写一个构造函数
function Student(_name,_sex,_age){
this.name = _name;
this.sex = _sex;
this.age = _age;
this.sayHello = function(){
console.log("大家好,我叫" + this.name);
}
}
var stu1 = new Student("张三","男",20);
var stu2 = new Student("李四","女",18);
无参构造函数
function Abc(){
console.log("hello world");
}
new abc;
工厂模式创建对象
我们在以后的时候,使用工厂模式来生产对象
function createStudent(_name,_sex,_age){
var obj = {
name:_name,
sex:_sex,
age:_age
};
return obj;
}
var stu1 = createStudent("张三","男",18);
通过上面的方式,也可以快速的创建对象,这种方式其实就是模拟了构造函数的new的过程
构造函数与普通函数的区别
构造函数与普通函数在书写上没有什么区别,关键在于调用方式上
1、构造函数使用 new 来调用,普通函数调用 函数名() 调用
2、构造函数的返回值一定是一个对象,而普通函数的返回值是根据return来决定
3、普通函数的this它指向的是window对象也就是浏览器窗口,而构造函数里面的this指向的是创建的这个对象
4、如果是通过new以构造函数的方式执行,在执行的时候如果没有实参需要传可以不写小括号
构造函数的命名规范
构造函数的函数名以大写字母开头
工厂模式与构造函数模式之间的区别
先来看代码
//创建学生工厂
function createStudent(_name,_sex,_age,_sid){
//创建对象
var obj = {
name:_name,
sex:_sex,
age:_age,
sid:_sid
}
return obj;
}
//学生对象
var stu1 = createStudent("张三","男",18,"s001");
stu1 instanceof Object //true;
使用构造函数创建对象
//学生构造函数
function Student(_name,_sex,_age,_sid){
this.name = _name;
this.sex = _sex;
this.age = _age;
this.sid = _sid;
}
var stu1 = new Student("张三","男",18,"s001");
stu1 instanceof Student //true
对象属性的调用
当我们完成一个对象的创建之后,怎么去调用对象的属性和方法
第一种调用方法
stu1.name; //调用name属性
stu1.sayHello() //调用stu1对象种的sayHlello方法并执行
但是这种调用方式有个小问题,有部分属性它调不了
var stu1 = {
name:"zhangsan",
1:"这是一个属性",
"a-b":"这是a-b属性"
}
stu1.1 //调不了
stu1.a-b //调不了
上面的代码调用就有问题了,碰到这种情况我们的常规调用就调不了
第二种调用方式:针对特殊属性名的调用
var stu1 = {
name:"zhangsan",
1:"这是一个属性",
"a-b":"这是a-b属性"
}
console.log(stu1[1]);
console.log(stu1["a-b"]);