js中的面向对象入门


Posted in Javascript onMarch 06, 2017

什么是对象

我们先来看高程三中是如何对对象进行定义的

"无序属性的集合,其属性可以包括基本值、对象或者函数",对象是一组没有特定顺序的的值。对象的没个属性或方法都有一个俄名字,每个名字都映射到一个值。

简单来理解对象就是由属性和方法来组成的

面向对象的特点

封装

对于一些功能相同或者相似的代码,我们可以放到一个函数中去,多次用到此功能时,我们只需要调用即可,无需多次重写。

在这里我们可以理解为创造对象的几种模式:单例模式,工厂模式,构造函数模式,原型模式等。

继承

子类可以继承父类的属性和方法

多态(重载和重写)

  • 重载:严格意义上说js中没有重载的功能,不过我们可以通过判断函数的参数的不同来实现不同的功能来模拟重载。
  • 重写:子类可以改写父类的属性和方法

javascript中的封装

单例模式

小王在一个小公司,就自己一个前端,所以他写js都是这样的

var a = 1;
function getNum(){
 return 1;
}

后来公司又招了个前端小明,于是变成他们2个一起写同一个js了。一天小王发现自己写的getNum方法出问题了,原来是小华写的js中也有个getNum的函数,代码合并后把他的覆盖掉了,于是便找小华理论去,经过一番妥协后,两人都把自己的代码改了改

var xiaoming = {
 num:1,
 getNum:function(){
 return 1;
 }
}
var xiaohua = {
 num:2,
 getNum: function(){
 return 2;
 }
}

这就是我们所谓的单例模式(命名空间)

我们把描述同一个事物的方法或者属性放到同一个对象里,不同事物之间的方法或者属性名相同相互也不会发生冲突。

单例模式的优劣

1.使用单例模式,我们可以实现简单的模块化开发

var utils = {
getCss:function(){
 //code
},
getByClass:function(){
 //code
},
setCss:function(){
 //code
}
}

我们可以把自己写好的工具方法放到一个单独的js文件中,然后直接引入即可。

2.避免了全局变量名的冲突

需要注意的是,我们在引入各个模块的时候,需要注意引入的顺序,引入顺序是按照各模块之间的相互依赖进行前后排列的;

3.缺点:

  • 单例模式只是一定程度上避免了变量名的冲突,但并不能彻底解决此问题,而且在不同的对象下,我们可能会有很多功能相同的代码,最终造成大量的冗余代码。
  • 单例模式让每个对象有了自己独立的命名空间,但是并不能批量生产的问题,每一个新的对象都要重新写一份一模一样的代码。
var person1 = {
 name:'小明',
 age:24,
 showName:function(){
  console.log('我的名字是:'+this.name)
 }
};
var person1 = {
 name:'小华',
 age:25,
 showName:function(){
  console.log('我的名字是:'+this.name)
 }
};

工厂模式

1.工厂模式其实就是把需要一个个的编写的对象,放在一个函数中统一的进行创建,说白了就是普通函数的封装。

2.工厂模式总共3步骤:

1)引进原材料 --- 创建一个空对象

2)加工原材料 --- 加工对象:给对象添加属性和方法;

3)输出产品 --- 返回对象:return 对象;

function CreatePerson(name,age){
 var obj={};//1.创建一个空对象
 //2.加工对象
 obj.name=name;
 obj.age=age;
 obj.showName=function(){
  console.log('我的名字是:'+this.name)
 };
 return obj;//3.输出对象;
}
var person1 = CreatePerson('小明',23)
var person2 = CreatePerson('小华',23)
person1.showName(); //我的名字是:小明
person2.showName(); //我的名字是:小华

工厂模式的优缺点

既然叫工厂模式,它就和我们周围的工厂一样,我们只需要把原材料放进去,就能得到我们需要的产品了。

工厂模式也解决了单例模式的批量生产的问题,避免了单例模式中的大量冗余代码,进行系统的封装,提高代码的重复利用率

不过工厂模式跟我们js内置类的调用方法不同

构造函数模式

  • 可以创建一个自定义的类,并且可以new出实例
  • 构造函数做的就是类和实例打交道。
//构造函数:首字母大写(约定俗成);
 function CreatePerson(name,age){ //创建一个自定义的类
 //构造函数中的this,都是new出来的实例
 //构造函数中存放的都是私有的属性和方法;
 this.name=name;
 this.age=age;
 this.showName=function(){
  console.log('我的名字是:'+this.name)
 }
 }
 //实例1
 var person1 = new CreatePerson('小明',25)
 //实例2
 var person2 = new CreatePerson('小华',24)

这里说一下工厂模式和构造函数模式的区别:

1. 在调用的时候不同:

工厂模式:调用的时候,只是普通函数的调用createPerson();

构造函数模式:new CreatePerson();

2. 在函数体内不同:

工厂模式有三步:1)创建对象 2)加工对象 3)返回对象;

构造函数模式只有1步: 只有加工对象; 因为系统默认会为其创建对象和返回对象;

3. 构造函数默认给我们返回了一个对象,如果我们非要自己手动返回的话:

    (1)手动返回的是字符串类型:对以前实例上的属性和方法没有影响;

    (2)手动返回的是引用数据类型:以前实例身上的属性和方法就被覆盖了;实例无法调用属性和方法;

构造函数的方法都是私有方法,每个实例调用的都是自己私有的方法,同样也会有许多重复的代码。

我们可以使用原型模式来解决每个实例中都有相同方法的函数的问题

原型模式

function CreatePerson(name,age){ 
 this.name=name;
 this.age=age;
 }
 // 我们把公有的方法放到函数的原型链上
 CreatePerson.prototype.showName = function(){
  console.log('我的名字是:'+this.name)
 } 
 var person1 = new CreatePerson('小明',25) 
 var person2 = new CreatePerson('小华',24)
 person1.showName() //小明

###### 原型模式的关键:

1)每个函数数据类型(普通函数,类)上,都有一个属性,叫prototype。

2)prototype这个对象上,天生自带一个属性,叫constructor:指向当前这个类;

3)每个对象数据类型(普通对象,prototype,实例)上都有一个属性,

   叫做__proto__:指向当前实例所属类的原型;

这3句话理解了,下边的东西就可以不用看了 //手动滑稽

通过例子我们来看这几句话是什么意思

function CreatePerson(name,age){
 this.name=name;
 this.age=age
}
CreatePerson.prototype.showName=function(){
  console.log('我的名字是:'+this.name)
}
var person1 = new CreatePerson('小明',25);
console.dir(person1)

在chrome浏览器控制台中显示

js中的面向对象入门

从图中可以看出,person1这个对象上有name和age两个属性,person1的__proto__指向了它的构造函数(CreatePerson)的prototype上,而且还有一个showName的方法。

并且它们中有一条链关联着: person1.__proto__ === CreatePerson.prototype

接着来看

function Foo(){
 this.a=1;
}
Foo.prototype.a=2;
Foo.prototype.b=3;
var f1 = new Foo; //没有参数的话括号可以省略
console.log(f1.a) //1
console.log(f1.b) // 3

以这个为例,当我们查找f1.a时,因为f1中有这个属性,所以我们得出 f1.a=1;当我们查找f1.b时,f1中没有这个属性,我们便顺着f1.__proto__这条链去它的构造器的prototype上找,所以我们得出了 f1.b = 3;

js中的面向对象入门

接着来说,Foo.prototype是个对象,那么它的__proto__指向哪里呢

还记的刚刚说的那句

每个对象数据类型(普通对象,prototype,实例)上都有一个属性,叫做__proto__:指向当前实例所属类的原型

此外,我们应该知道

每一个对象都是function Object这个构造函数的实例

js中的面向对象入门

所以我们可以接着还原这个原型图

js中的面向对象入门

等等,图上貌似多了个个Object.prototype.__proto__ 指向了null,这是什么鬼?

我们这么来理解,Object.prototype是个对象,那么它的__proto__指向了它的构造函数的prototype上,最后发现了还是指向它自身,这样转了个圈貌似是无意义的,于是便指向了null还没完,我们发现对象都是函数(构造器)创造出来的,那么函数是谁创造的呢?石头里蹦出来的么?

在js中,function都是由function Function这个构造器创造的,每一个函数都是Function的实例

js中的面向对象入门

现在基本上我们就能得出了完整的原型图了

js中的面向对象入门

是不是有点乱?根据我们刚刚讲的是能把这个图理顺的,这里需要注意下,Function.__proto__是指向它的prototype的

多说一点,判断数据类型的方法时,我们知道有个instanceof的方法

比如

A instanceof B

instanceof判断的规则就是:

沿着A的__proto__这条线查找的同时沿着B的prototype这条线来找,如果两条线能找到同一个引用(对象),那么就返回true。如果找到终点还未重合,则返回false。

再来看我们之前的那个例子

function Foo(){
 this.a=1;
}
Foo.prototype.a=2;
Foo.prototype.b=3;
var f1 = new Foo; //没有参数的话括号可以省略
console.log(f1.a) //1
console.log(f1.b) // 3

当我们查找f1.a时,因为f1中有这个属性,所以我们得出 f1.a=1;

当我们查找f1.b时,f1中没有这个属性,我们便顺着f1.__proto__这条链去它的构造器的prototype上找,所以我们得出了 f1.b = 3;

当我们查找一个对象的属性时,先在这个对象的私有空间内查找,如果没找到,就顺着对象的__proto__这条链去它的构造器的ptototype上查找,如果还没找到,接着沿__proto__向上查找,直到找到Object.prototype还没有的话,这个值就为undefined,这就是所谓的原型链

列举下网页中的一些相关的原型链

js中的面向对象入门

有兴趣的同学可自行通过浏览器控制台看看我们常用的方法都是在哪个类上定义的,比如getElementsByTagName,addEventListener等等

继承

在这里就主要说一下组合继承(call + 原型链)

function Father(){
 this.xxx= 80;
 this.yyy= 100;
 this.drink = function(){}
}
Father.prototype.zzz= function(){}
var father = new Father;
function Son(){
 this.aaa = 120;
 this.singing = function(){}
 Father.call(this);
}
Son.prototype = new Father;
Son.prototype.constructor = Son;
var son = new Son
console.dir(son)

js中的面向对象入门

这么写有个不好的地方就是:子类私有的属性中有父类私有的属性,子类公有的属性中也有父类私有的属性;

根据我们前边的知识,我们可以这么来改写

function Father(){
 this.xxx= 80;
 this.yyy= 100;
 this.drink = function(){}
}
Father.prototype.zzz= function(){}
var father = new Father;
function Son(){
 this.aaa = 120;
 this.singing = function(){}
 Father.call(this); //利用call继承了父类的私有属性
}
Son.prototype.__proto__ = Father.prototype
var son = new Son
console.dir(son)

最后来一张思维导图

js中的面向对象入门

图片如果放大也看不清的话 下载地址

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
javascript模仿msgbox提示效果代码
Jun 10 Javascript
javascript笔试题目附答案@20081025_jb51.net
Oct 26 Javascript
jquery animate 动画效果使用说明
Nov 04 Javascript
Jquery优化效率 提升性能解决方案
Sep 06 Javascript
jquery form表单序列化为对象的示例代码
Mar 05 Javascript
灵活使用数组制作图片切换js实现
Jul 28 Javascript
微信公众号 客服接口的开发实例详解
Sep 28 Javascript
vue学习之mintui picker选择器实现省市二级联动示例
Oct 12 Javascript
代码详解Vuejs响应式原理
Dec 20 Javascript
vue 指定组件缓存实例详解
Apr 01 Javascript
layui实现给某一列加点击事件
Oct 26 Javascript
sharp.js安装过程中遇到的问题总结
Apr 02 Javascript
jQuery插件FusionCharts实现的2D面积图效果示例【附demo源码下载】
Mar 06 #Javascript
Vue 2.x教程之基础API
Mar 06 #Javascript
jQuery实现获取h1-h6标题元素值的方法
Mar 06 #Javascript
一道面试题引发的对javascript类型转换的思考
Mar 06 #Javascript
JavaScript函数参数的传递方式详解
Mar 06 #Javascript
jQuery实现遍历复选框的方法示例
Mar 06 #Javascript
jQuery.cookie.js使用方法及相关参数解释
Mar 06 #Javascript
You might like
PHP 中英文混合排版中处理字符串常用的函数
2007/04/12 PHP
解析MySql与Java的时间类型
2013/06/22 PHP
关于使用runtimeStyle属性问题讨论文章
2007/03/08 Javascript
jQuery选中select控件 无法设置selected的解决方法
2010/09/01 Javascript
jquery实现网站超链接和图片提示效果
2013/03/21 Javascript
Jquery easyUI 更新行示例
2014/03/06 Javascript
一个判断抢购时间是否到达的简单的js函数
2014/06/23 Javascript
JS长整型精度问题实例分析
2015/01/13 Javascript
jQuery浏览器CSS3特写兼容实例
2015/01/19 Javascript
js比较日期大小的方法
2015/05/12 Javascript
jQuery实现的简单提示信息插件
2015/12/08 Javascript
Bootstrap Validator 表单验证
2016/07/25 Javascript
详解Javascript中的原型OOP
2016/10/12 Javascript
JS实现的抛物线运动效果示例
2018/01/30 Javascript
详解a标签添加onclick事件的几种方式
2019/03/29 Javascript
vuejs中父子组件之间通信方法实例详解
2020/01/17 Javascript
vue.config.js中配置Vue的路径别名的方法
2020/02/11 Javascript
python实现的登录和操作开心网脚本分享
2014/07/09 Python
python基础教程之面向对象的一些概念
2014/08/29 Python
go语言计算两个时间的时间差方法
2015/03/13 Python
Python函数式编程指南(四):生成器详解
2015/06/24 Python
python 读写中文json的实例详解
2017/10/29 Python
Python实现的归并排序算法示例
2017/11/21 Python
分析python动态规划的递归、非递归实现
2018/03/04 Python
python 随机打乱 图片和对应的标签方法
2018/12/14 Python
Python装饰器限制函数运行时间超时则退出执行
2019/04/09 Python
python 非线性规划方式(scipy.optimize.minimize)
2020/02/11 Python
Pandas实现一列数据分隔为两列
2020/05/18 Python
python Tornado框架的使用示例
2020/10/19 Python
使用CSS3来实现滚动视差效果的教程
2015/08/24 HTML / CSS
心得体会范文
2014/01/04 职场文书
财务总监管理职责范文
2014/03/09 职场文书
学生社团文化节开幕式主持词
2014/03/28 职场文书
学雷锋志愿者活动总结
2014/06/27 职场文书
协会周年庆活动方案
2014/08/26 职场文书
《风不能把阳光打败》读后感3篇
2020/01/06 职场文书