好程序员web前端学习路线之Javascript面向对象,面向对象是使用对象,面向对象开发就是使用对象开发。
面向过程就是用过程的方式进行开发,面向对象是对面向过程的封装
面向对象的三大特性:
抽象性:
如果需要一个对象描述数据,需要抽取这个对象的核心数据,提出需要的核心属性和方法,不在特定的环境下无法明确对象的具体意义。
狭义的抽象,也就是代码里的抽象,就是把一些相关联的业务逻辑分离成属性和方法(行为),这些属性和方法就可以构成一个对象。
这种抽象是为了把难以理解的代码归纳成与现实世界关联的概念,比如美食这样一个对象:属性可以归纳出“海底捞”、“自助餐”、“盖饭”等等;方法(行为)可以归纳出“贵”、“实惠”、“便宜”等。
var fineFood = {
name: '海底捞',
seat: '贵宾座',
Number: 4,
shout: function() {
console.log('贵贵贵'); //这里是你的业务逻辑代码,这里我就简单用这个来代替
},
eat: function() {
console.log('吃土吧,哈哈!');
},
Reason: function() {
console.log('贵是有原因');
}
};
封装性:
对象是将数据与功能组合在一起,简单的理解这就是封装
Javascript对象就是键值对的集合,键值如果是数据就称之为属性,如果键值是函数就称之为方法。
对象就是将属性与方法封装起来
方法将是过程封装起来
封装就是将抽象出来的数据与对数据的操作封装在一起。数据被保护在内部,程序的其他部分只有通过授权的操作才能进行对数据进行操作。
JS封装只有两种状态,一种是公开的,一种是私有的。
function Person(name,seatl){
this.name=name; //公开
var seat=seat; //私有
this.showInfo=function(){ //公开
window.alert(this.name+" "+seat);
}
function showInfo2(){ //把函数私有化
window.alert("你好"+this.name+" "+seat);
}
}
var p1 = new Person('Cece', 20, 10);
window.alert(p1.name + " is " +p1.age); //Cece is undefined
p1.showInfo();//Cece 20
p1.showInfo2();//报错
构造函数方式与原型方式给对象添加方法的区别:
//1.通过构造函数方式给对象添加方法
function fineFood(name){
this.name=name;
this.seat=function(){
window.alert("有请"+this.name + "几位贵宾");
}
}
var fineFood1=new fineFood("aa");
var fineFood2=new fineFood("bb");
if(fineFood1.shout==fineFood.shout){
window.alert("相等");
}else{
window.alert("不相等");
}
//会输出“不相等”
//2.通过原型方式给对象添加方法
function fineFood(name){
this.name=name;
}
fineFood.prototype.shout=function(){
window.alert("有请"+this.name + "几位贵宾");
}
var fineFood1=new fineFood("aa");
var fineFood2=new fineFood("bb");
if(fineFood1.shout==fineFood2.shout){
window.alert("相等");
}else{
window.alert("不相等");
}
//会输出“相等”
通过prototype给所有的对象添加方法,但是这种方式不能去访问类的私有变量和方法;说明通过构造函数来分配成员方法,给每个对象分配一份独立的代码。这样的弊端就是如果对象实例有很多,那函数的资源占用就会很大,而且有可能造成内存泄漏。而原型法是大家共享同一份代码,就不会有那种弊端。
因此,通过构造函数添加成员方法和通过原型法添加成员方法的区别:
1).通过原型法分配的函数是所有对象共享的;
2).通过原型法分配的属性是独立的;
3).如果希望所有的对象使用同一个函数,最好使用原型法添加方法,这样比较节省内存。
继承性
函数是可以继承另外一个对象,构造函数实例化出来的对象除了本身成员外还有拥有被继承对象的成员。
原型链是一种机制,指的是 JavaScript 每个对象都有一个内置的 proto 属性指向创建它的构造函数的 prototype(原型)属性。
原型链的作用是为了实现对象的继承,要理解原型链,需要先从函数对象、constructor、new、prototype、proto 这五个入手。
函数对象
在 JavaScript 里,函数即对象,程序可以随意操控它们。比如,可以把函数赋值给变量,或者作为参数传递给其他函数,也可以给它们设置属性,甚至调用它们的方法。
// 普通对象:
var o1 = {};
var o2 = new Object();
//函数对象:
function f1(){};
var f2 = function(){};
var f3 = new Function('string','console.log(string)');
简单的说,凡是使用 function 关键字或 Function 构造函数创建的对象都是函数对象。而且,只有函数对象才拥有 prototype (原型)属性。
constructor 构造函数
函数还有一种用法,就是把它作为构造函数使用。像 Object 和 Array 这样的原生构造函数。此外,也可以创建自定义的构造函数,从而自定义对象类型的属性和方法。
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
console.log(this.name);
};
}
var person1 = new Person("Stone", 28, "aa");
var person2 = new Person("Sophie", 29, "bb");
我们创建了一个自定义构造函数 Person(),并通过该构造函数创建了两个普通对象 person1 和 person2,这两个普通对象均包含3个属性和1个方法。
你应该注意到函数名 Person 使用的是大写字母 P。按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头。这个做法借鉴自其他面向对象语言,主要是为了区别于 JavaScript 中的其他函数;因为构造函数本身也是函数,只不过可以用来创建对象而已。
new 操作符
要创建 Person 的新实例,必须使用 new 操作符。以这种方式调用构造函数实际上会经历以下4个步骤:
-
创建一个新对象;
-
将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
-
执行构造函数中的代码(为这个新对象添加属性);
- 返回新对象。