一、关于面向对象

编程可以分为面向过程编程和面向对象编程
面向过程:就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用
面向对象:把一件事分解成一个个对象,然后由对象之间分工合作。面向对象是以对象功能来划分问题,而不是步骤。

对象工厂

当需要创建具有相同结构的多个对象时,采用对象字面量或者new Object将很难适应,因此采用对象工厂模式来创建一个对象

{// 很繁琐let tom = {name:"Tom",age:20,sex:"male"}let jerry = {name:"Jerry",age:18,sex:"female"}
}
{// 对象工厂函数function createPerson(name,age,sex){return {name,age,sex}};let tom = createPerson("Tom",20,"male");console.log(tom); // { name: 'Tom', age: 20, sex: 'male' }let jerry = createPerson("Jerry",18,"female");console.log(tom == jerry); // false
}

对象工厂也有问题,对象工厂本身是一个普通函数,用于表达对象结构时,描述性不强。对象工厂没有解决对象标识的问题,即创建的对象是什么类型,利用构造函数就可以解决对象工厂的问题

构造函数

构造函数的首字母要大写,与普通函数作为区分。
其工作原理:

  1. 在内存中创建一个新对象
  2. 这个新对象内部的[[Prototype]]特性被赋值为构造函数的prototype属性
  3. 构造函数内部的this被赋值为这个新对象(即this指向新对象)
  4. 执行构造函数内部的代码(给新对象添加属性)
  5. 如果构造函数返回非空对象,则返回该对象,否则返回刚创建的新对象(所以构造函数不需要return)
{// 创建与使用function Person(name,age){this.name = name;this.age = age;this.show = function(){console.log(`hello:${this.name}`);}}let tom = new Person("tom",20);let jack = new Person("Jack",22);tom.show(); // hello:tom
}

构造函数用于创建特定类型的对象,如Object和Array等,以函数的形式为自己的对象类型定义属性和方法。
上面的例子中,tom和jack分别保存着Person的不同实例,这两个对象都有一个constructor属性指向Person。

{console.log(tom.constructor == Person); // trueconsole.log(jack.constructor == Person); // true
}

constructor是用于标识对象类型的,不过一般使用instanceof操作符来确定对象的类型,所有自定义对象都继承自Object

{console.log(tom instanceof Person); // trueconsole.log(tom instanceof Object); // true
}

构造函数的问题

构造函数虽然有用但也不是没有问题,主要问题在于其定义的方法会在每个实例上都创建一遍,因此对于刚刚的例子来说,每次实例化对象时都会创建show方法,但这个两个实例对象不是相等的,因此方法也不等,但是要做的事却是一样的,因此没必要定义两个不同的方法实例。解决这个问题可以通过把函数定义转移到构造函数外面。

{    function Person(name,age){this.name = name;this.age = age;this.show = show}function show(){console.log(`hello:${this.name}`)}let tom = new Person("tom",20);let jack = new Person("Jack",22);tom.show(); // hello:tom// 不是相等的,因此显得冗余console.log(tom.show == jack.show); // false
}

show函数被定义到了全局,在构造函数内部show属性等于全局的show函数,所以构造函数的实例对象共享了在全局上的show函数,这样虽然解决了重复的问题,但是全局作用域也被混乱了,因为show函数只能在实例对象上调用,如果构造函数有多个方法那么就要写多个全局函数,显得很麻烦,因此可以通过原型模式来解决。

原型模式

每一个函数都有一个prototype属性,这个属性是一个对象,包含应该由特定引用类型的实例共享的属性和方法。实际上这个对象就是通过调用构造函数实例化的对象的原型。因此可以使用这个原型对象来定义属性或者方法,这样就可以被构造函数对象实例所共享。

{function Person(name,age){this.name = name;this.age = age;}Person.prototype.grade = 'grade one';// constructor属性指回构造函数console.log(Person.prototype.constructor == Person); // true
}

{// 构造函数的创建与使用function Mouse(name,age){this.name = name;this.age = age;}Mouse.prototype.from = 'Cartoon'; // 都会被继承let jerry = new Mouse('Jerry',19);let mickey = new Mouse('Mickey',20)// 当在构造函数原型上创建属性(或方法)时,会被改构造函数的额所有对象所共享。console.log(jerry.from); // Cartoonconsole.log(Object.getPrototypeOf(jerry) == Mouse.prototype); // true,同一个原型console.log(Object.keys(jerry)); // keys返回可枚举的自己的属性。["name","age"]console.log(Object.getOwnPropertyNames(jerry)); // 跟上面一样console.log(jerry.hasOwnProperty("from")); // false,判断不了继承的属性console.log('from' in jerry); // in判断可枚举的所有属性(包括继承属性)因此为true// 一旦对象自身对继承自原型的属性赋值,则创建了一个属于自己的同名属性,并覆盖了继承自原型的属性。mickey.from = 'Disney';console.log("Jerry From:",jerry.from); // Jerry From: Cartoonconsole.log("Mickey From:",mickey.from); // Mickey From: Disney
}

构造函数、原型与实例对象的关系

  • 每个构造函数都有一个原型对象
  • 原型有一个属性指回构造函数(constructor)
  • 实例对象有一个内部指针[[Prototype]]指向原型

原型链

  • 当对象原型是另一个构造函数的实例,如此迭代,形成了一连串的继承关系就是原型链
  • 原型链表达了对象与对象之间的继承关系

原型链的问题

{function Animal() {this.colors = ["white", "black"];}function Mouse(name, age) {this.name = name;this.age = age;}// 强制指定原型对象,表达继承关系Mouse.prototype = new Animal(); // 从Mouse的原型上继承animal构造函数的实例let m1 = new Mouse("Mickey", 10);console.log(m1.name, m1.colors);m1.colors.push("red");let m2 = new Mouse("Miney", 9);console.log(m2.colors); // [ 'white', 'black', 'red' ],收到了影响
}

问题在于当原型中包含引用值时(如数组),在各实例间共享的是该引用值的引用。当某个实例修改该属性时会影响全部实例。并且子类在实例化时不能给父类传递参数

盗用构造函数:在子类构造函数中调用父类构造函数,并将子类当前实例指定为构造函数的上下文。

{function Animal(type){this.colors = ['white','black'];this.type = type}function Mouse(name,age,type = 'Mouse'){// 把父构造函数的this通过call改为当前构造函数的thisAnimal.call(this,type); // 父类构造函数的盗用,解决传参的问题this.name = name;this.age = age;}Animal.prototype.show = function(){console.log(this.type,this.colors);}// 强制指定原型对象,表达继承关系Mouse.prototype = new Animal(); // 从Mouse的原型上继承animal构造函数的实例Mouse.prototype.constructor = Mouse; // 强制指定构造函数为原构造函数let m1 = new Mouse('Mickey',10);m1.show(); // 就是Animal上面的show方法,this就为当前生成的实例对象的this Mouse [ 'white', 'black' ]m1.colors.push('red'); console.log(m1.name,m1.type,m1.colors); // Mickey Mouse [ 'white', 'black', 'red' ]let m2 = new Mouse('Duck',9);m2.show();m2.colors.push('pink');console.log(m2.name,m2.type,m2.colors); // Duck Mouse [ 'white', 'black', 'pink' ]console.log(m1 instanceof Mouse); // trueconsole.log(m1 instanceof Animal); // trueconsole.log(Object.keys(m1)); // [ 'colors', 'type', 'name', 'age' ]console.log(Mouse.prototype.isPrototypeOf(m2)); // trueconsole.log(m1.constructor == Mouse); // trueconsole.log(m1.constructor == Animal); // false
}

二、ES6新增的class关键字

ES6中新引入了class关键字具有正式定义类的能力,class是一种新的语法糖可以显式的用来创建一个类,虽然表面上看起来可以支持正式的面向对象编程,但实际上它背后使用的仍然是原型和构造函数的概念

{// ES5定义类和继承function Car(title){this.title = title;}Car.prototype.drive = function(){return 'Venoom';}const car = new Car("BMW");console.log(car.title); // BMWconsole.log(car.drive()); // Venoom// ES5实现继承function Benz(color,title){Car.call(this,title); // 把当前对象作为this,改变父构造函数的this指向this.color = color;}Benz.prototype = Object.create(Car.prototype);Benz.prototype.constructor = Benz;const ben = new Benz("red","focus");console.log(ben.title); // focusconsole.log(ben.drive()); // Venoom
}
{// ES6定义类和继承class People{constructor(options){ this.name = options.name; }say(){return 'hello';}}// ES6的继承,使用extends关键字class Boy extends People{constructor(options){super(options);this.age = options.age;}}const boy = new Boy({name:'小李',age:20})console.log(boy.name); // 小李console.log(boy.say()); // hello
}

JavaScript学习笔记(十一):面向对象编程相关推荐

  1. javascript 学习笔记之面向对象编程(二):继承多态

    ~~接上篇~~上一篇实现了类的实现以及类成员变量和方法的定义,下面我们来了解下面向对象中两个最重要的特性:继承和多态. 继承 js中同样可以实现类的继承这一面向对象特性,继承父类中的所有成员(变量和属 ...

  2. 学习笔记----MATLAB面向对象编程入门02--类的方法、构造函数

    本系列内容为<MATLAB面向对象编程–从入门到设计模式>学习笔记,特此说明. 定义类的方法 类的方法(Method)一般用来查询(Query)对象的状态,或者向对象发出一个命令(Comm ...

  3. Python学习笔记:面向对象编程(4)

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  4. Python学习笔记:面向对象编程(3)

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  5. Python学习笔记:面向对象编程(2)

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  6. Python学习笔记:面向对象编程(1)

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  7. JavaScript学习随记——面向对象编程(继承)

    @Example:基于原型链的继承 <!DOCTYPE HTML> <html><head><meta http-equiv="Content-Ty ...

  8. 简明Python教程学习笔记_6_面向对象编程

    面向对象编程:https://www.liaoxuefeng.com/wiki/897692888725344/923030496738368 面向对象高级编程:https://www.liaoxue ...

  9. 【廖雪峰Python学习笔记】面向对象编程OOP

    面向对象编程 OOP:Object Oriented Programming 程序的基本单元:对象 [ = 数据 + 操作数据的函数] [属性 + 方法] 三大特点:数据封装.继承和多态 OPP中的计 ...

  10. C++ Primer 学习笔记_72_面向对象编程 --句柄类与继承[续]

    面向对象编程 --句柄类与继承[续] 三.句柄的使用 使用Sales_item对象能够更easy地编写书店应用程序.代码将不必管理Item_base对象的指针,但仍然能够获得通过Sales_item对 ...

最新文章

  1. no判断 python yes_python的判断 - osc_kewb5r6m的个人空间 - OSCHINA - 中文开源技术交流社区...
  2. 2014-02-20
  3. java 问题排查_JAVA问题排查笔记
  4. 全国高等学校计算机等级考试(江西考区)一级笔试试卷a,全国高等学校计算机等级考试(江西考区)一级笔试试卷A...
  5. Java需要掌握的底层知识_java程序员需要知道的底层知识(一)
  6. jmeter web监听结果_监听器-聚合报告监听性能测试结果
  7. .net开发微信公众号(3)-接收微信推送的消息
  8. 【Python】用pip安装python库下载超时的解决办法
  9. 黑客都使用什么编程语言?
  10. element-ui的el-menu路由模式下选中无颜色
  11. linux 快照工具,技术预览:CentOS 7中利用Snapper GUI管理系统快照
  12. 使用电子签章确立在线医疗电子病历的法律地位
  13. 数组和链表的增删改查速度比较
  14. 最邻近差值算法(nearest)和双线性插值算法(bilinear)
  15. springboot权限系统
  16. 为华生物COOH-PEG-MAL羧基-聚乙二醇-马来酰亚胺的简介及应用说明
  17. innosetup如何读取注册表及其字段值
  18. MATLAB编程实现哈夫曼编码
  19. Word中的图文框和文本框
  20. 第15章Stata时间序列分析

热门文章

  1. 安装adobe系列软件提示已损坏,无法打开,如何解决?
  2. C语言入门高级教学(上)
  3. 利用wce Hash注入身份验证连接MSSQL
  4. 如何彻底关闭Windows10系统更新带来的天气、资讯和兴趣删除开机任务栏右下角的广告自动弹窗程序
  5. cgb2008-京淘day19
  6. javaScript 数字转为英文
  7. 计算机考研推荐信,考研复试推荐信范文
  8. MasterAlign软件使用说明——运行参数
  9. loj #6070. 「2017 山东一轮集训 Day4」基因
  10. mvn package、mvn install和mvn deploy区别