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高级程序设计 学习笔记 js高级技巧
Sep 20 Javascript
JS实现为表格动态添加标题的方法
Mar 31 Javascript
js限制文本框的输入内容代码分享(3类)
Aug 20 Javascript
浅谈JavaScript中的string拥有方法的原因
Aug 28 Javascript
jQuery定义插件的方法
Dec 18 Javascript
跨域请求的完美解决方法(JSONP, CORS)
Jun 12 Javascript
JavaScript常用代码书写规范的超全面总结
Sep 11 Javascript
详解JavaScript按概率随机生成事件
Aug 02 Javascript
AngularJS ionic手势事件的使用总结
Aug 09 Javascript
9种使用Chrome Firefox 自带调试工具调试javascript技巧
Dec 22 Javascript
详解在Node.js中发起HTTP请求的5种方法
Jan 10 Javascript
js实现弹窗效果
Aug 09 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
APMServ使用说明
2006/10/23 PHP
PHP安全配置
2006/12/06 PHP
比较简单的百度网盘文件直链PHP代码
2013/03/24 PHP
PHP 扩展Memcached命令用法实例总结
2020/06/04 PHP
读jQuery之四(优雅的迭代)
2011/06/20 Javascript
如何获取select下拉框的值(option没有及有value属性)
2013/11/08 Javascript
js只执行1次的函数示例
2016/07/20 Javascript
Nodejs调用Dll模块的方法
2018/09/17 NodeJs
Vue.js 使用v-cloak后仍显示变量的解决方法
2018/11/19 Javascript
JavaScript函数式编程(Functional Programming)声明式与命令式实例分析
2019/05/21 Javascript
jQuery实现高度灵活的表单验证功能示例【无UI】
2020/04/30 jQuery
微信小程序实现列表左右滑动
2020/11/19 Javascript
python文件读写并使用mysql批量插入示例分享(python操作mysql)
2014/02/17 Python
Python-嵌套列表list的全面解析
2016/06/08 Python
使用python3.5仿微软记事本notepad
2016/06/15 Python
利用python实现命令行有道词典的方法示例
2017/01/31 Python
Python 实现数据库更新脚本的生成方法
2017/07/09 Python
Python编程把二叉树打印成多行代码
2018/01/04 Python
python实现在图片上画特定大小角度矩形框
2018/10/24 Python
Python面向对象程序设计之私有属性及私有方法示例
2019/04/08 Python
Flask模板引擎之Jinja2语法介绍
2019/06/26 Python
Python hashlib模块加密过程解析
2019/11/05 Python
用python解压分析jar包实例
2020/01/16 Python
解决pycharm 格式报错tabs和space不一致问题
2021/02/26 Python
canvas学习和滤镜实现代码
2018/08/22 HTML / CSS
phpquery中文手册
2021/03/18 PHP
MIKI HOUSE美国官方网上商店:日本领先的婴儿和儿童高级时装品牌
2020/06/21 全球购物
绘画设计学生的个人自我评价
2013/09/20 职场文书
大学生求职推荐信
2013/11/27 职场文书
外贸英语专业求职信范文
2013/12/25 职场文书
汽车专业学生自我评价
2014/01/19 职场文书
计算机科学系职业生涯规划书
2014/03/08 职场文书
法制宣传教育方案
2014/05/09 职场文书
2014年9.18纪念日演讲稿
2014/09/14 职场文书
小学英语新课改心得体会
2016/01/22 职场文书
《颐和园》教学反思
2016/02/19 职场文书