面向对象概述

面向对象(Object Oriented)简称OO,它是一种编程思维,用于指导我们如何应对各种复杂的开发场景。

这里说的对象(Object),意思就是事物,在面向对象的思维中,它将一切都看作是对象,并以对象为切入点去思考问题。

使用面向对象的思维去开发程序,我们首先思考的是这个系统中有哪些对象(事物),它们各自有什么属性(特征),又有什么方法(行为),这样一来,就可以把系统分解为一个一个的对象,然后对每个对象进行单独研究,以降低系统的整体复杂度。

学习面向对象,我们不仅要学习它的技术知识,更重要的是学习这种思考程序的方式,这种思维方式跟我们过去开发程序有很大的区别。在过去,我们完成一个功能的时候,往往思考的是完成该功能的步骤,先做什么,再做什么,如果怎么样,就怎么怎么样……,这种过去的思维模式,我们称之为面向过程。

面向过程并不是错误的,只是它面对复杂的问题时显得有些捉襟见肘。

面向过程和面向对象最大的区别在于,面向过程思考的重心和切入点是事情,面向对象思考的重心和切入点是事物。

在面向对象的世界中,它将一切都看作是对象。这里的对象,包罗万象,它可以是现实世界中看得见摸得着的实体:人、小猫、小狗、飞机、课桌、铅笔、电视等等等等,都可以看作是对象。它也可以是某些领域中的抽象体:订单、价格计算器、dom元素、日期等等等等,它们也被看作是对象。

因此,在OO的世界里,有一句至理名言——一切皆为对象。

javascript语言是支持面向对象开发的语言,本系列教程中,将一步步讲解如何使用它进行面向对象开发,同时会进一步探寻它背后深层次的原理。

注意:本系列教程的重心,将放在面向对象开发的技术层面(即面向对象编程,Object Oriented Programming,OOP)。

对于面向对象思想层面(即面向对象设计,Object Oriented Design,OOD),本教程不做过多讲解。因为面向对象思想的建立并非一朝一夕,它不是靠读文章读出来的,虽然好的文章可以对你有启发作用,但更多的,这种思想是靠常年累月的代码量练出来的,是靠不断的分析、重构想出来的。

本教程希望的是,你能够通过学习面向对象开发,激发你的思考,引起你对另一种开发方式的关注,逐渐建立起面向对象的思维。

创建对象

对象即事物,一切皆对象。

其实你在之前的开发中,应该不止一次的接触过对象,有些是浏览器自带的对象,比如:dom对象、window对象、document对象等;有些则是你根据功能需要自己创建的,比如:用户对象、学生对象等。

在JS中,创建一个对象非常的简单,通过一对{}即可创建一个对象,下面的代码你应该并不会陌生:

const user1 = {    loginid: "bangbangji",    loginpwd: "123456",    name: "棒棒鸡"};const user2 = {    loginid: "xiaobaitu",    loginpwd: "654321",    name: "小白兔"};

上面的代码应该这样理解,创建了两个对象,分别把它们赋值给了变量user1和user2。

为什么要强调这一点呢?因为真正的对象不是user1和user2,而是那一对大括号及其里面的内容{...},在后面讲解对象赋值原理时还会详细讲解这一点。

上面这种创建对象的写法,即使用两个大括号来表示对象{...},叫做对象的字面量表示法。

使用字面量表示法来创建对象的好处是简单易懂,但它不好的地方在于无法应用面向对象开发中的一些高级特性。

下面的代码,展现了另一种创建对象的方式,即使用关键字new来创建对象:

const user1 = new Object(); //相当于:const user1 = {};user1.loginid = "bangbangji"; user1.loginpwd = "123456"; user1.name = "棒棒鸡";const user2 = new Object(); //相当于:const user2 = {};user2.loginid = "xiaobaitu"; user2.loginpwd = "654321"; user2.name = "小白兔";

这样的代码虽然看似繁琐了很多,但实际上它才是对象原本的创建方式。上面的代码和第一种方式效果完全一致。

实际上,在JS语言中,所有的对象都是使用new关键字创建的。即便你使用的是字面量表示法,JS引擎最终也会将其转换为这种方式。因此,对象的字面量表示法仅仅是JS语言的一个语法糖,要创建对象,最终都是要使用new关键字的。因此,在后文中,每一个示例,我都会用两种方式来实现对象的创建。

语法糖(Syntactic sugar),也译为糖衣语法,是指语言层面的一些便捷语法,它仅仅是为开发者提供的一种高效的编码方式,并不改变底层的实现原理。

属性和方法

我们过去使用对象,往往是为了将多个变量整合到一个变量上,其实,这种思想就是面向对象的一种核心思想——封装。

面向对象有三大显著特征:封装、继承、多态

那些整合到一个对象中的变量,我们称之为对象的属性。属性往往是一个名词,表示对象所拥有的特征。

const user1 = {    loginid: "bangbangji", //loginid为对象的属性,表示用户账号    loginpwd: "123456", //loginpwd为对象的属性,表示用户密码    name: "棒棒鸡" //name为对象的属性,表示用户姓名};const user2 = new Object(); user2.loginid = "xiaobaitu";//loginid为对象的属性,表示用户账号user2.loginpwd = "654321";//loginpwd为对象的属性,表示用户密码user2.name = "小白兔";//name为对象的属性,表示用户姓名

对象的属性还可以是一个对象或者数组或者其他任意类型,用于表示多层次的结构:

const user1 = {    loginid: "bangbangji",    loginpwd: "123456",    name: "棒棒鸡",    //属性address也是一个对象    address: {        province: "四川省",        city: "成都市"    } };//输出:四川省-成都市console.log(`${user1.address.province}-${user1.address.city}`); const user2 = new Object(); user2.loginid = "xiaobaitu"; user2.loginpwd = "654321"; user2.name = "小白兔"; user2.address = new Object(); //属性address也是一个对象user2.address.province = "四川省"; user2.address.city = "南充市";//输出:四川省-南充市console.log(`${user2.address.province}-${user2.address.city}`);

对象除了有特征,还会有一些行为,这些行为我们称之为对象的方法。方法往往是一个动词,表示对象所拥有的行为,在代码层面,方法表现为函数。

const user1 = {    loginid: "bangbangji",    loginpwd: "123456",    name: "棒棒鸡",    //sayHello(打招呼)属于对象方法,它是一个函数,表示对象的行为    sayHello: function () {        console.log("你好!");    } }; user1.sayHello(); //调用对象的方法,输出:你好!const user2 = new Object(); user2.loginid = "xiaobaitu"; user2.loginpwd = "654321"; user2.name = "小白兔";//sayHello(打招呼)属于对象方法,它是一个函数,表示对象的行为user2.sayHello = function () {    console.log("你好!"); }; user2.sayHello(); //调用对象的方法,输出:你好!

可以看出,方法和属性在书写上并没有本质的差别,只不过属性是一个普通的值,方法是一个函数而已。

this关键字

我们现在考虑一下,在之前的示例中出现的sayHello方法,假设我们现在要对其功能做一点改造,我们希望该方法要输出对象的姓名和账号,于是,得到了下面的代码:

const user1 = {    loginid: "bangbangji",    loginpwd: "123456",    name: "棒棒鸡",    //sayHello(打招呼)属于对象方法,它是一个函数,表示对象的行为    sayHello: function () {        console.log("你好!我是棒棒鸡,我的账号是bangbangji");    } }; user1.sayHello(); //调用对象的方法,输出:你好!我是棒棒鸡,我的账号是bangbangjiconst user2 = new Object(); user2.loginid = "xiaobaitu"; user2.loginpwd = "654321"; user2.name = "小白兔";//sayHello(打招呼)属于对象方法,它是一个函数,表示对象的行为user2.sayHello = function () {    console.log("你好!我是小白兔,我的账号是xiaobaitu"); }; user2.sayHello(); //调用对象的方法,输出:你好!我是小白兔,我的账号是xiaobaitu

这种方式结果固然正确,但是考虑一下100个用户的场景……不敢想象是不?这还仅仅是一个打招呼的方法,如果方法里面代码多一点,复杂一点,会更加棘手。

由于同一类对象(比如这里的用户对象)都具有共同的行为——打招呼,我们何不把这个方法函数提出来呢?就像下面这样:

//提取出来的共同方法function sayHello(){    //怎么办?输出哪个对象的姓名和账号?    console.log("你好!我是???,我的账号是???"); }const user1 = {    loginid: "bangbangji",    loginpwd: "123456",    name: "棒棒鸡",    sayHello }; user1.sayHello(); //输出:你好!我是???,我的账号是???const user2 = new Object(); user2.loginid = "xiaobaitu"; user2.loginpwd = "654321"; user2.name = "小白兔"; user2.sayHello = sayHello; user2.sayHello(); //输出:你好!我是???,我的账号是???

这样虽然解决了代码重复的问题,但新的问题又来了,虽然我们知道每个用户对象都具有打招呼的方法,但是每个对象的属性值不一样,打招呼的时候,我到底输出哪个对象的属性值呢?

于是,JS给我们提供了一个关键字this,它指代的是当前对象,即调用方法的对象,于是我们就可以解决这个问题了:

//提取出来的共同方法function sayHello(){    //this指代当前调用方法的对象    console.log(`你好!我是${this.name},我的账号是${this.loginid}`); }const user1 = {    loginid: "bangbangji",    loginpwd: "123456",    name: "棒棒鸡",    sayHello };//user1调用sayHello时,方法运行过程中的this指代user1user1.sayHello(); //输出:你好!我是棒棒鸡,我的账号是bangbangjiconst user2 = new Object(); user2.loginid = "xiaobaitu"; user2.loginpwd = "654321"; user2.name = "小白兔"; user2.sayHello = sayHello;//user2调用sayHello时,方法运行过程中的this指代user2user2.sayHello(); //输出:你好!我是小白兔,我的账号是xiaobaitu

我们在sayHello函数中使用了this关键字,当函数运行时,该关键字指代调用该函数的对象,即谁在调用我,我里面的this就指代谁。在阅读代码的时候,你可以把this读作我的,以便于你理解它。

借助了神奇的this关键字,就解决了重复代码的问题,之后无论创建多少个用户对象,我们都可以使用同一个方法了。

关于this关键字,目前你需要记住以下两点:

this关键字只能书写在函数内。

this关键字在函数运行的时候才能确定指代的是谁,函数运行前谁也无法知道它将指代谁。

由于javascript语言本身的特性,函数中的this关键字会带来很多坑(比如直接调用sayHello函数,this指代谁呢?)。后面会专门拿一章出来讲解this。

总结

面向对象(OO)是一种编程思维,以对象为切入点分析解决问题,这种思维需要长期的练习才能逐渐建立,而我们学习的是面向对象技术层面的东西。

创建对象可以使用字面量表示法和new关键字,字面量表示法是一个语法糖,JS引擎最终会将其变为new关键字方式创建对象。

对象包含属性和方法,分别表示对象的特征和行为,它们没有本质的区别,只是行为提现为一个函数

在函数中可以使用this关键字来指代**当前对象(调用函数的对象)

JS面向对象系列教程 — 对象的基本操作的更多相关文章

  1. [js高手之路] es6系列教程 - 对象功能扩展详解

    第一:字面量对象的方法,支持缩写形式 //es6之前,这么写 var User = { name : 'ghostwu', showName : function(){ return this.nam ...

  2. 页面循环绑定(变量污染问题),js面向对象编程(对象属性增删改查),js字符串操作,js数组操作

    页面循环绑定(变量污染问题) var lis = document.querySelectorAll(".ul li") for ( var i = 0 ; i < lis. ...

  3. JS面向对象编程:对象

    一般面向过程的写法都是写很多function,坏处:1.代码复用不好 2.函数名称容易重复冲突 下面介绍面向对象的写法: 在JS中每个函数function都是一个对象. 比如,下面这个就是一个对象,我 ...

  4. JS面向对象编程,对象,属性,方法。

    document.write('<script type="text/javascript" src="http://api.map.baidu.com/api?v ...

  5. js面向对象知识点之对象属性 创建对象 总结中

    昨天面试出了一道面试题 本人我做错了 于是痛定思痛 再过一遍面向对象 var name="一体机"; var value="infolist"; //构造函数 ...

  6. Vue.js入门系列教程(二)

    过滤器:filter 全局过滤器 <!DOCTYPE html> <html lang="en"> <head> <meta charse ...

  7. Vue.js入门系列教程(一)

    基本的Vue代码结构 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> ...

  8. JS面向对象设计-理解对象

    不同于其他面向对象语言(OO,Object-Oriented),JS的ECMAScript没有类的概念, 它把对象定义为"无序属性(基本值.对象.函数)的集合",类似于散列表. 每 ...

  9. Vue.js入门系列教程(三)

    序言

随机推荐

  1. js实现简易打点计时器

    很简单的实现一个打点计时器,规定从start至end,每次加1,每次打印间隔100ms,并且返回取消方法. 代码如下: //打点计时器,每间隔100毫秒+1 function count(start, ...

  2. 洛谷3871 [TJOI2010]中位数 维护队列的中位数

    题目描述 给定一个由N个元素组成的整数序列,现在有两种操作: 1 add a 在该序列的最后添加一个整数a,组成长度为N + 1的整数序列 2 mid 输出当前序列的中位数 中位数是指将一个序列按照从 ...

  3. java源码学习

    Collection List ArrayList LinkedList Vector Stack Set HashSet TreeSet Map HashMap TreeMap LinkedHash ...

  4. Spring配置方式

    Spring配置方式 第一阶段:xml配置     在spring 1.x时代,使用spring开发满眼都是xml配置的bean,随着项目的扩大, 我们需要把xml配置文件分放到不同的配置文件中,那时 ...

  5. Spring-statemachine给end状态设置action

    Spring-statemachine版本:当前最新的1.2.3.RELEASE版本 builder.configureStates() .withStates() .initial(generate ...

  6. VC:当前不会命中断点,还没有为该文档载入不论什么符号

    VS2013中设置的断点无效:"当前不会命中断点,还没有为该文档载入不论什么符号".问题主要出在没有生成调试信息.解决方法例如以下: (1)项目-〉属性-〉配置属性-〉C/C++- ...

  7. Mesh BRep Shapes

    Mesh BRep Shapes eryar@163.com Abstract. 当对OpenCASCADE的BRep表示法的数据结构有了一定的理解后,建议可以自己实现一个显示数据生成的功能,即网格剖 ...

  8. UE4的JSON读写方式&lt;一&gt;

    声明:全部权利保留. 转载必须说明出处:http://blog.csdn.net/cartzhang/article/details/41009343 UE4的Json的解析博客地址: http:// ...

  9. 流水线技术原理和Verilog HDL实现

    所谓流水线处理,如同生产装配线一样,将操作执行工作量分成若干个时间上均衡的操作段,从流水线的起点连续地输入,流水线的各操作段以重叠方式执行.这使得操作执行速度只与流水线输入的速度有关,而与处理所需的时 ...

  10. Jesse's Code

    题目描述 Jesse是个数学迷,他最喜欢研究“哥德巴赫猜想”,因此他的计算机密码也都采用素数. 但一直用同一个密码是不安全的,所以他要经常更换他的密码.但他只允许自己的密码中出现某些数字,且密码的每一 ...