JavaScript面向对象编程及设计模式

  • JavaScript面向对象编程及设计模式
    • 一、面向对象编程
      • 1、简述
      • 2、面向对象编程特点
      • 3、封装
      • 4、this
      • 5、call和apply
      • 6、new
      • 7、继承
      • 8、多态

JavaScript面向对象编程及设计模式

一、面向对象编程

1、简述

面向对象是一种程序的设计思想,与之对应的编程思想叫做面向过程

**例如:**比如我想要用代码描述一个场景,有一只叫做xiaoA的猫,吃了一个苹果,又吃了一条鱼,然后有一只叫做xiaoB的猫,吃了一根香蕉

// 面向过程
function xiaoAEatApple() {}
function xiaoAEatFish() {}
function xiaoBEatBanana() {}
xiaoAEatApple();
xiaoAEatFish();
xiaoBEatBanana();
// 面向对象
function Cat(name) {this.name = name
}
Cat.prototype.eat = function(something) {}
let xiaoA = new Cat('xiaoA')
let xiaoB = new Cat('xiaoB')
xiaoA.eat('apple')
xiaoA.eat('fish')
xiaoB.eat('banana')

2、面向对象编程特点

  • 面向对象注重于抽象事务,而面向过程注重于叙述事务
  • 面向对象逻辑清晰有条理,而面向过程比较方面
  • JS通过函数和原型,模拟了传统面向对象编程中类的概念实现了面向对象的编程模式
  • 面向对象的编程思想,主要为了实现3件事,封装,继承和多态

3、封装

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 普通方法// let carA = {//     name: 'xiaoA',//     eat() {//         console.log('xiaoA eat something')//     }// }// let carB = {//     name: 'xiaoB',//     eat() {//         console.log('xiaoB eat something')//     }// }// let carC = {//     name: 'xiaoC',//     eat() {//         console.log('xiaoC eat something')//     }// }// 代码重复量多,需要封装// 封装// 使用工厂模式封装// function createCat(name) {//     let obj = {}//     obj.name = name;//     obj.eat = () => {//         console.log(name + 'eat something')//     }//     return obj;// }// let catA = createCat(xiaoA)// let catB = createCat(xiaoB)// let catC = createCat(xiaoC)// 使用面向对象的方式进行封装function CreateCat(name) { // 构造函数this.name = name;this.eat = () => {console.log(this.name + 'eat something')}}let catA = new CreateCat('xiaoA')let catB = new CreateCat('xiaoB')let catC = new CreateCat('xiaoC')</script>
</head>
<body></body>
</html>

4、this

// this
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// this // 在函数执行的时候会在函数内部创建两个变量,arguments, this// arguments是存储着实参的一个类数组变量// this 指向函数的执行上下文 (谁调用这个函数, this就指向谁)function aaa (a, b) {console.log(arguments)}aaa(1, 2, 3, 4) // 数组 var arr = {1, 2, 3, 4}// 类数组对象 var arrObj = {0: 1, 1: 2, 2: 3, 3: 4, length: 4}function bbb() {console.log(this)}var objA = {b: bbb,c: {d: bbb,}}bbb(); // this 指向 windowobjA.b() // this 指向 objAobjA.c.d(); // this 指向 objA.c</script>
</head>
<body></body>
</html>

5、call和apply

// call-apply
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// call apply 用来动态改变this的指向// function aaa() {//     console.log(this)// }// var objA = {//     b: aaa// }// aaa() // this 指向window// objA.b() // this 指向objA// aaa.call(objA); // call 函数将aaa内的this 从指向 window 改成了 指向objA// objA.b.call(window); // call 函数将aaa内的this 从指向 objA 改成了 指向windowfunction aaa(name, age) {// console.log(this)this.name = namethis.age = age}var objA = {b: aaa}aaa.call(objA, 'xiaoA', 23); // call 函数将aaa内的this 从指向 window 改成了 指向objAconsole.log(objA.name, objA.age); // 打印 xiaoA 23objA.b.call(window, ['xiaoB', 30]); // call 函数将aaa内的this 从指向 objA 改成了 指向windowconsole.log(window.name, window.age)objA.b.call(window, 'xiaoB', 30); // call 函数将aaa内的this 从指向 objA 改成了 指向windowconsole.log(window.name, window.age)objA.b.apply(window, ['xiaoB', 30]); // call 函数将aaa内的this 从指向 objA 改成了 指向windowconsole.log(window.name, window.age)</script>
</head>
<body></body>
</html>

6、new

new 做了哪些操作
1.创建一个空对象
2.将构造函数的prototype属性赋值给新对象的__proto__属性
3.将构造函数的this指向新对象
4.执行构造函数的代码
5.将新对象返回

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>function CreateCat(name) { this.name = name}let catA = new CreateCat('xiaoA')console.log(catA.name)/*new 做了哪些操作1.创建一个空对象2.将构造函数的prototype属性赋值给新对象的__proto__属性3.将构造函数的this指向新对象4.执行构造函数的代码5.将新对象返回*/// 闭包,自执行函数var catB = (function() {var obj = {}obj.__proto__ = CreateCat.prototype;CreateCat.call(obj, 'xiaoB');return obj})()console.log(catB.name)</script>
</head>
<body></body>
</html>

7、继承

在声明函数的时候,会自动创建一个prototype属性,我们管他叫做原型, 一般用来存放实例公用的方法

prototype:
是子类继承的父类的属性,也就是当调用子类构造函数时,总的来说,这里只能是继承一个具体的对象,不能是一个类(es6后会有所改变)

prototype内容:

__proto__内容
是类继承父类之后,子类对象中的父类属性,里面的属性是可以通过子类对象直接取的,不需要用__proto__。
这里检索逻辑是:
先检索子类的直接属性是否存在,然后再检索__proto__,然后就是俄罗斯套娃,一层一层套下去,到最后还是没有就返回 undefined

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>/*new 做了哪些操作1.创建一个空对象2.将构造函数的prototype属性赋值给新对象的__proto__属性3.将构造函数的this指向新对象4.执行构造函数的代码5.将新对象返回*/// 在声明函数的时候,会自动创建一个prototype属性,我们管他叫做原型, 一般用来存放实例公用的方法function CreateCat(name) { this.name = name;} // console.log('prototype:', CreateCat.prototype)CreateCat.prototype.eat = function(something) {console.log(this.name + ' eat ' + something)}var catA = new CreateCat('xiaoA')catA.eat('fish')/*carA:1. {}  // 第一步创建新对象2. {__proto__: CreateCat.prototype}3. {__proto__: CreateCat.prototype,name:  'xiaoA'}4.执行构造函数的代码5.return*/// 在JS里规定,访问对象属性的时候,如果对象下面没有这个属性,则去他下面的__proto__去寻找,如果没有,就一直向下寻找直到没有__proto__为止console.log(catA)// 类式继承function A(name) {this.name = name;this.list = [1, 2, 3]}A.prototype.getName = () => {console.log(this.name);}function SubA(name) {this.subName = 'sub' + this.name;}SubA.prototype = new A()var sa1 = new SubA('sa1');console.log(sa1.list, sa1.name); // 打印出 [1, 2, 3] undefined/*new A() -> {name: undefined,list: [1,2,3],__proto__: {getName: fn,constructor....}}new SubA('sa1') -> {subName: 'sub sa1',__proto__: {name: undefined,list: [1,2,3],__proto__: {getName: fn,constructor....}}}// 类式继承的问题1.这种方法不支持父构造函数带参数2.父构造函数里的方法和属性都会变成共有属性*/var sa1 = new SubA('sa1'); var sa2 = new SubA('sa2'); A.prototype.getName = function() {console.log('fixed getName')}A.prototype.newFn = function() { console.log('new Fn')}sa1.getName(); // 打印 fixed getNamesa2.newFn();   // 打印 new Fn// 构造函数继承function A(name) {this.name = name;this.list = [1, 2, 3]}A.prototype.getName = () => {console.log(this.name);}function SubA(name) {A.call(this, name)this.subName = 'sub' + this.name;}var sa1 = new SubA('xiaoA');console.log(sa1.name, sa1.subName); // 打印出 xiaoA subxiaoAsa1.getName(); // 报错/*new SubA('xiaoA'); -> {__proto__: {constructor....},name: 'xiaoA',list: [1, 2, 3],subName: 'sub xiaoA'}// 构造函数继承问题1.不能继承父构造函数的原型方法*/// 组合式继承function A(name) {this.name = name;this.list = [1, 2, 3]}A.prototype.getName = () => {console.log(this.name);}function SubA(name) {A.call(this, name)this.subName = 'sub' + this.name;}SubA.prototype = new A()var sa1 = new SubA('xiaoA');console.log(sa1.name, sa1.subName); // 打印出 xiaoA subxiaoAsa1.getName(); // xiaoA/*new A() ->  {name: undefined,list: [1, 2, 3],__proto__: {getName: fn}}new SubA('xiaoA'); -> {name: 'xiaoA',list: [1, 2, 3],subName: 'sub xiaoA',__proto__: {name: undefined,list: [1, 2, 3],__proto__: {getName: fn}},}// 组合式继承问题1.__proto__里的属性没有用2.执行了两次父构造函数问题点在于: SubA.prototype = new A()*/// 4.寄生组合式继承function A(name) {this.name = name;this.list = [1, 2, 3]}A.prototype.getName = () => {console.log(this.name);}function SubA(name) {A.call(this, name)this.subName = 'sub' + this.name;}// SubA.prototype = new A() // 优化这一句代码function inheritPrototype(subClass, superClass) { // 子构造函数 父构造函数function F() {};F.prototype = superClass.prototype;subClass.prototype = new F()subClass.prototype.constructor = subClass; // 可有可无}inheritPrototype(SubA, A)var sa1 = new SubA('xiaoA');console.log(sa1.name, sa1.subName); // 打印出 xiaoA subxiaoAsa1.getName(); // xiaoA</script>
</head>
<body></body>
</html>

8、多态

多态: 表示不同对象调用相同方法会产生不同结果

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// 多态: 表示不同对象调用相同方法会产生不同结果function Base() {}Base.prototype.initial = function() {this.init()}function SubA() {this.init = function () { console.log('subA init')}}function SubB() {this.init = function () { console.log('subB init')}}SubA.prototype = new Base();SubB.prototype = new Base();var subA = new SubA()var subB = new SubB()subA.initial(); subB.initial();</script>
</head>
<body></body>
</html>

JavaScript面向对象编程浅析相关推荐

  1. 《JavaScript面向对象编程指南》——第1章 引言1.1 回顾历史

    本节书摘来自异步社区<JavaScript面向对象编程指南>一书中的第1章,第1.1节,作者: [加]Stoyan Stefanov 译者: 凌杰 更多章节内容可以访问云栖社区" ...

  2. 《JavaScript面向对象编程指南》——1.3 分析现状

    本节书摘来自异步社区<JavaScript面向对象编程指南>一书中的第1章,第1.3节,作者: [加]Stoyan Stefanov 译者: 凌杰 更多章节内容可以访问云栖社区" ...

  3. (二)Javascript面向对象编程:构造函数的继承

    Javascript面向对象编程:构造函数的继承 这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例. 今天要介绍的是,对象之间的"继承&q ...

  4. javascript 面向对象编程(工厂模式、构造函数模式、原型模式)

    javascript 面向对象编程(工厂模式.构造函数模式.原型模式) CreateTime--2018年3月29日17:09:38 Author:Marydon 一.工厂模式 /*** 工厂模式*/ ...

  5. JavaScript面向对象编程深入分析

    JavaScript面向对象编程深入分析 一. Javascript 面向对象编程:封装 Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又 ...

  6. 《javascript面向对象编程指南》读书笔记

    <javascript面向对象编程指南>读书笔记 <javascript面向对象编程指南>读书笔记 第一章 面向对象的JavaScript 第二章 基本数据类型与流程控制 变量 ...

  7. (转)Javascript 面向对象编程(一):封装

    它们都是非常优秀的Javascript读物,推荐阅读. 笔记分成三部分.今天的第一部分是讨论"封装"(Encapsulation),后面的第二部分和第三部分讨论"继承&q ...

  8. 《JavaScript面向对象编程指南》——1.7 训练环境设置

    本节书摘来自异步社区<JavaScript面向对象编程指南>一书中的第1章,第1.7节,作者: [加]Stoyan Stefanov 译者: 凌杰 更多章节内容可以访问云栖社区" ...

  9. 《JavaScript面向对象编程指南》—第128页错误指正

    最近在阅读<JavaScript面向对象编程指南第2版>,感觉很有帮助.今晚发现一个小错误,想指正一下. 如图,书中第128页: 书中的第三个例子代码如下: "potato&qu ...

最新文章

  1. 论Oracle 11g数据库备份与恢复策略
  2. Zepto.js库touch模块代码解析
  3. java 获取打印机缺纸_第三章软件
  4. 异常处理-RestFul的异常处理
  5. 如何设置Fiddler来拦截Java代码发送的HTTP请求,进行各种问题排查
  6. CVPR2021 | 北航商汤耶鲁口头报告
  7. python 制定识别图片的某些区域_python批量识别图片指定区域文字内容
  8. FreeMarker 日期转换
  9. linux网络适配器驱动程序怎么安装,英特尔?服务器适配器 — Linuxixgbe* 基础驱动程序概述和安装...
  10. BoltDB 一个简单的纯 Go key/value 存储 [译]
  11. Windows命令行安装程序管理工具 - Scoop
  12. (转F001) Rust : 解引用,自动解引用
  13. 记录自己Kettle下载全过程
  14. 禁用键盘上的某些按键
  15. Mac电脑 绑定阿里云企业邮箱
  16. 关于正负数比较大小的问题
  17. 【踩坑实录】Mission planner+Ardupilot飞控固件配置教程
  18. 西安地图 百度西安高清卫星地图 最高19级 可商用地图
  19. Mac安装eDEX-UI以及后续Python环境配置
  20. uniapp中 onReady, onLoad, onShow区别

热门文章

  1. 你的键盘上有boss key吗
  2. SpringCloud 面试问题
  3. 一起学ReactNative(3) 实现网易云音乐旋转唱片效果
  4. mp3转成cd专用软件
  5. Java I/O 相关面试题
  6. Django增删改查--图书管理系统
  7. linux 图形界面无法进入,无法进入图形界面的解决过程
  8. Java 编写应用程序,使用for循环语句计算8+88+888…前10项之和。
  9. 深度优先搜索 python_黄哥Python:图深度优先算法(dfs)
  10. 输入字母判断是否为大写