JavaScript之对象 (八):对象类型的使用、值类型和引用类型、函数的this指向、工厂方法创建对象、构造函数和类、new创建对象

跳转目录🚀

篇章知识点
JavaScript之邂逅 (一)认识编程语言及其历史、JS的历史、JS的分类、JS运行引擎、JS应用场景
JavaScript之基本语法 (二)JS的编写方式、noscript元素的使用、JS的注意事项、JS交互方式、JS语句和分号、JS注释方式
JavaScript之变量与数据类型 (三)认识JavaScript变量、变量的定义和规范、数据类型和typeof、常见的数据类型、数据类型的转换
JavaScript之常见的运算符 (四)运算符和运算元、算数运算符、赋值运算符、自增和自减、比较运算符、运算符优先级
JavaScript之分支语句与逻辑运算符 (五)if分支语句、if分支语句、if…else if…else…语句、三元运算符、逻辑运算符、switch语句
JavaScript之循环语句 (六)认识循环语句、while 循环、do……while 循环、 for 循环、 break与continue关键字
JavaScript之函数 (七)认识JavaScript函数、函数的声明和调用、函数的递归调用、局部和全局变量、函数表达式的写法、立即执行函数使用
JavaScript对象 (八)对象类型的使用、值类型和引用类型、函数的this指向、工厂方法创建对象、构造函数和类、new创建对象
JavaScript之常见内置类 (九)认识包装类型、数字类型Number、数学类型Math、字符串类型String、数组Array使用详解、Date类型的使用

1. 对象类型的使用

1.1 认识对象类型

基础数据类型可以存储一些简单的值,但是现实世界的事物抽象成程序时,往往比较复杂。

  • 比如一个人,有自己的特性(比如姓名、年龄、身高),有一些行为(比如跑步、学习、工作)
  • 比如一辆车,有自己的特性(比如颜色、重量、速度),有一些行为(比如行驶)

在这里插入图片描述

  • 对象类型:是一种存储键值对(key-value)的更复杂的数据类型,我们需要使用对象类型将特性和行为组织到一起
    1. {……}创建,里面包含键值对"key: value"
    2. 键值对可以是属性和方法(在对象中的函数称之为方法)
    3. 其中key是字符串(也叫做属性名property name ,ES6之后也可以是Symbol类型,后续学习),但是在定义对象的属性名时, 大部分情况下引号都是可以省略的
    4. 其中value可以是任意类型,包括基本数据类型、函数类型、对象类型等
/*
      两个术语: 函数/方法
         函数(function): 如果在JavaScript代码中通过function默认定义一个结构, 称之为是函数.
         方法(method): 如果将一个函数放到对象中, 作为对象的一个属性, 那么将这个函数称之为方法.
    */
    function foo() {
    }

    // key: 字符串类型, 但是在定义对象的属性名时, 大部分情况下引号都是可以省略的
    var person = {
      // key: value
      name: "why",
      age: 18,
      height: 1.88,
      "my friend": {
        name: "kobe",
        age: 30
      },
      run: function() {
        console.log("running")
      },
      eat: function() {
        console.log("eat foods")
      },
      study: function() {
        console.log("studying")
      }
    }

1.2 创建对象

  • 对象的属性用逗号,分隔

  • 对象的创建方法有很多,包括三种:

    1. 对象字面量(Object Literal):通过{ }
      在这里插入图片描述

    2. new Object + 动态添加属性
      在这里插入图片描述

    3. new 其他类 构造函数
      在这里插入图片描述

1.3 对象的常见操作

// 1.定义了一个对象
    var info = {
      name: "why",
      age: 18,
      friend: {
        name: "kobe",
        age: 30
      },
      running: function() {
        console.log("running~")
      }
    }

  1. 访问对象的属性
    在这里插入图片描述

  2. 修改对象的属性
    在这里插入图片描述

  3. 添加对象的属性
    在这里插入图片描述

  4. 删除对象的属性
    在这里插入图片描述

1.4 方括号和引号的使用

在对象中属性名(键)是字符串类型,但是在定义对象的属性名时, 大部分情况下引号都是可以省略的。当我们用点符号去访问多词属性,JavaScript是无法理解的。

在这里插入图片描述

访问对象的两种方式

  1. 对象名.属性名
    • 点符号要求 key 是有效的变量标识符
    • 并且不包含空格不以数字开头也不包含特殊字符(允许使用 $ 和 _ )
  2. 对象名["属性名"]
    • 中括号访问键名时需要搭配引号访问,即字符串 ,也可以放入值为字符串的变量名
    • 方括号的操作在定义或者操作属性时更加的灵活
      在这里插入图片描述

1.5 对象的遍历

对象的遍历(迭代):表示获取对象中所有的属性和方法。

遍历对象的方法

  1. 普通for循环:主要用到该方法,Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组。

    // 1.普通for循环
        var infoKeys = Object.keys(info)
        for (var i = 0; i < infoKeys.length; i++) {
          var key = infoKeys[i]
          var value = info[key]
          console.log(`key: ${key}, value: ${value}`)
        }
    
  2. for in 遍历方法:

    // 2.for..in..: 遍历对象
        for (var key in info) {
          var value = info[key]
          console.log(`key: ${key}, value: ${value}`)
        }
    

2. 值类型和引用类型

2.1 栈内存和堆内存

  • 我们知道程序是需要加载到内存中来执行的,我们可以将内存划分为两个区域栈内存和堆内存
    • 原始类型占据的空间是在栈内存中分配的
    • 对象类型占据的空间是在堆内存中分配的

在这里插入图片描述
备注:目前我们先掌握堆和栈的概念即可,后续我们会学习图中的其他知识

在这里插入图片描述

2.2 值类型和引用类型

  1. 原始类型也被称之为值类型:即在变量中保存的是值本身
    在这里插入图片描述

  2. 以对象类型也被称之为引用类型:在变量中保存的是对象的“引用”,即地址
    在这里插入图片描述

2.3 五种典型现象

  1. 现象一: 两个对象的比较
    在这里插入图片描述

  2. 现象二: 引用的赋值
    在这里插入图片描述

  3. 现象三: 值传递
    在这里插入图片描述

  4. 现象四: 引用传递, 但是在函数中创建了一个新对象, 没有对传入对象进行修改
    在这里插入图片描述

  5. 现象五: 引用传递, 但是对传入的对象进行修改
    在这里插入图片描述

3. this 关键字

3.1 为什么需要this

  • 在常见的编程语言中,几乎都有this关键字,但是在JavaScript中的this和常见的面向对象语言中的this不太一样
    • 常见面向对象的编程语言中,比如Java、C++、Swift、Dart等等一系列语言中,this通常只会出现在类的方法中,首先需要有一个类,类中的方法(特别是实例方法)中,this代表的是当前调用对象
    • JavaScript中:this更加灵活,无论是它出现的位置还是它代表的含义,下面我们开始了解JavaScript中this的指向

我们来看一下编写一个obj的对象,有this和没有this的区别:
在这里插入图片描述

3.2 函数中this的指向

函数中是有一个this的变量, this变量在大多数情况下会指向一个对象,我们也知道除了this外,还有一个arguments对象保存传入的所有参数

目前掌握两个this的判断方法
1. 在全局环境下,this指向window

// 情况一: 如果普通的函数被默认调用, 那么this指向的就是window
    // function foo(name, age) {
    //   console.log(arguments)
    //   console.log(this)
    // }
    // foo("abc", 123)

    function sayHello(name) {
      console.log(this)
    }

    sayHello()  //window
  1. 通过对象调用,this指向调用的对象
 // 情况二: 如果函数它是被某一个对象来引用并且调用它, 那么this会指向这个对象(调用的那个调用)
    var obj = {
      name: "why",
      running: function() {
        console.log(this)
        // console.log(obj)
        // console.log(this === obj)
      }
    }
    obj.running() //obj

this指向练习题:

var obj = {
      name: "why",
      running: function() {
        console.log(this)
        // console.log(obj)
        // console.log(this === obj)
      }
    }
    obj.running() //obj

    // 考验题目
    // 1.题目一:
    var fn = obj.running
    fn() // window

    // 2.题目二:
     function bar() {
      console.log(this)
    }
    var obj = {
      name: "why",
      bar: bar
    }
    obj.bar()// obj对象
    bar()// window对象

3.3 this在开发中的作用

当我们的对象中的方法执行是,需要一些参数,如果我们有很多方法都需要参数,那我们手动的去一个个添加是很麻烦的。
在这里插入图片描述

我们可以利用this的特性,即通过对象调用,指向的是调用的对象,即可以从对象中取值
在这里插入图片描述

4. 类和对象

4.1 类和对象的思维方式

  • 如果需要在开发中创建一系列的相似的对象,我们应该如何操作呢?比如:
    • 游戏中创建一系列的英雄(英雄具备的特性是相似的,比如都有名字、技能、价格,但是具体的值又不相同)
    • 学生系统中创建一系列的学生(学生都有学号、姓名、年龄等,但是具体的值又不相同)

4.2 创建对象的方案

  1. 方案一(不可行) :直接创建一系列的对象
    在这里插入图片描述

  2. 方案二 工厂函数:我们可以封装一个函数,这个函数用于帮助我们创建一个对象,我们只需要重复调用这个函数即可,工厂模式其实是一种常见的设计模式

在这里插入图片描述

分析:工厂方法创建对象有一个比较大的问题:我们在打印对象时,对象的类型都是Object类型,我们希望从某些角度来说,创建的对象应该他有一个他们共同的类型,因此,我们需要看一下另外一种模式:构造函数的方式

  1. 通过工厂函数创建的对象:因为{}默认时是通过new Object()生成的空对象,Object也是一个构造函数或类
    在这里插入图片描述
  2. 通过构造函数创建的对象
    在这里插入图片描述

4.3 认识构造函数

构造函数(也称 构造器 constructor): 我们通过调用构造函数来创建对象,在其他编程语言中,构造函数是存在于类中的一个方法,称之为构造方法。但是在JavaScript中的构造函数有点不一样,构造函数其实就是类的扮演者

  • 在ES5之前,我们都是通过function来声明一个构造函数(类)的,之后通过new关键字来对其进行调用
  • 在ES6之后,JavaScript可以像别的语言一样,通过class来声明一个类

像之后我们会学到内置对象,也可以称内置类,比如像系统默认给我们提供的Date就是一个构造函数,也可以看成是一个类

4.4 类和对象的关系

  • 现实生活中:我们往往是根据一份描述/一个模板创建一个实体对象的,比如水果是统称,而苹果、橘子、葡萄等是具体的对象。
  • 编程语言中也是一样: 首先必须有一份描述, 在这份描述中说明将来创建出来的对象有哪些属性(成员变量)和行为(成员方法)
    在这里插入图片描述

4.5 构造函数的使用

需要使用 this关键字 以及 new关键字

  • 在函数中的this一般指向某一个对象
  • 如果一个函数被new操作符调用
    1. 在内存中创建一个新的对象(空对象);
    2. 这个对象内部的[[prototype]]属性会被赋值为该构造函数的prototype属性 (后续了解)
    3. 构造函数内部的this,会指向创建出来的新对象
    4. 执行函数的内部代码(函数体代码)
    5. 如果构造函数没有返回非空对象,则返回创建出来的新对象
    function coder(name, age, height) {
          this.name = name
          this.age = age
          this.height = height
          this.running = function() {
            console.log("running~")
          }
        }
    
        // 在函数调用的前面加 new 关键字(操作符)
        var stu1 = new coder("why", 18, 1.88)
        var stu2 = new coder("kobe", 30, 1.98)
        console.log(stu1, stu2)
    

接下来,我们可以用构造函数的方式来实现一下批量创建学生。

4.5 构造函数(类)的总结

我们前面说过,在JavaScript中类的表示形式就是构造函数。

构造函数与普通函数的区别

  • 构造函数也是一个普通的函数,从表现形式来说,和千千万万个普通的函数没有任何区别
  • 如果这么一个普通的函数被使用new操作符来调用了,那么这个函数就称之为是一个构造函数

构造函数与普通函数的命名:在ES5之前为了区分构造函数和普通函数我们一般这么操作

  • 构造函数:使用大驼峰命名
  • 普通函数:使用小驼峰命名
 // 创建一系列的对象
    // 构造函数的名称: 使用大驼峰
    function Person() {

    }
    // 普通函数: 使用小驼峰
    function sayHello() {

    }

    // 构造函数创建对象
    var p1 = new Person()
    console.log(p1)

    // 平时创建普通的对象
    // new Object()
    var obj1 = {}
    var obj2 = new Object()
    var obj3 = new Person()

4.6 额外补充

4.6.1 全局对象window

在浏览器中存在一个全局对象 window

  1. 作用一:查找变量时,最终会找到window上
  2. 作用二:将一些浏览器全局提供给我们的变量/函数/对象, 放在window对象上面

注意: 使用var定义的变量会被默认添加到window上面

4.6.2 函数也是对象

我们在给一个对象添加成员的操作同样可以用于函数上,因为函数的本质也是对象。

// 定义对象类型的变量
    // 地址 - 指针 - 引用
    var obj = {} // 堆内存
    var foo = function() {} // 堆内存
    function bar() {} // 堆内存

    console.log(typeof obj) // object
    console.log(typeof foo) // function -> object

    // var stu = new Student() // stu是一个Student -> Person
  1. 给函数对象添加属性

  2. 构造函数上(类上面)添加的函数, 称之为类方法

 var info = {}
    info.name = "abc"

    function sayHello() {
      let name = "fsj"
    }
    sayHello.age = 18
    console.dir(sayHello)
    console.log(sayHello.age)

    function Dog() {

    }
    // 构造函数上(类上面)添加的函数, 称之为类方法
    Dog.running = function () { }
    Dog.running()
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值