JavaScript基础知识点整理(一)——数据类型、判定、转换、this指向

news2024/12/29 9:16:54

JavaScript是每一位前端开发者都必备的技能,接下来会分章节文章阐述介绍每一部分的内容。

JavaScript基础整理①

  • 1、JavaScript类型
  • 2、原始(primitive)类型
  • 3、对象(Object)类型
  • 4、类型判定
    • 4.1、typeof
    • 4.2、instanceof
    • 4.3、Object.prototype.toString.call
  • 5、类型转换
    • 5.1、对象转原始类型
  • 6、四则运算符
    • 6.1、比较运算符
  • 7、this


1、JavaScript类型

JavaScript数据类型分为两大类:

  • 原始类型number、string、nul、undefined、boolean、symbol
  • 对象类型:三大类,分别是内部对象(本地对象和内置对象)、宿主对象自定义对象
    • 本地对象:ES提供的需要实例化new才能够使用的对象:Object、Function、Array、String、Boolean、Number、Date、Error、EvalError、RangeError、ReferenceError、syntaxError、TypeError、URIError;
    • 内置对象,也就是GlobalMath,其中JavaScript的全局属性有infinity-代表正的无穷大的数值、NaN-指示某一个数值不是数字值、undefined-指示未定义的数值。
    • 宿主对象:执行JavaScript脚本的环境所提供的对象,是浏览器提供的对象,所有的BOM和DOM都是宿主对象
    • 自定义对象:包括对象字面量方式(通过JSON创建对象)、工厂模式、构造函数模式、原型模式、组合使用构造函数模式和原型模式、其他模式动态原型模式、寄生构造函数模式、稳妥构造函数模式)。

2、原始(primitive)类型

在JavaScript中,存在着7种原始数值,分别是:

  • boolean
  • null
  • undefined
  • number
  • string
  • symbo
  • bigint

原始类型存储的都是数值,没有函数可以调用,不会存在如下:undefined.toString()
在这里插入图片描述

注意:如果采用'1'.toString()是可以正常使用,这是由于'1'已经被强制转换为了String类型也就是对象类型,可以调用toString方法。

JavaScript的number类型是浮点类型,使用会遇到bug,例如0.1 + 0.2 !== 0.3;

string类型数值不可以改变,无论使用任何方法;

3、对象(Object)类型

对象类型和原始类型不一样,原始类型存储的是数值,一般保存在栈上对象类型存储的是地址-指针,数据保存在堆上

创建一个对象类型时候,计算机会在堆内存种开辟空间保存数值,开发者需要找到该内存空间,这个空间会拥有一个指针(地址)

const a = []

对于常量a而言,设定内存地址#001,那么地址#001的位置保存了数值[],常量a存放了地址#001,给出如下示例代码:

const a = []
const b = a
b.push(1)

当我们将变量赋值给另外一个变量时,复制的是原本变量的地址(指针),也就是说当前变量 b 存放的地址(指针)也是 #001。因此当我们对任一变量进行数据修改的时候,等同于修改存放在地址(指针) #001 上的值,所以就导致了两个变量的值都发生了改变。

若函数参数是对象的时候:

function test(person) {
  person.age = 26
  person = {
    name: 'yyy',
    age: 30
  }

  return person
}
const p1 = {
  name: 'yck',
  age: 25
}
const p2 = test(p1)
console.log(p1) // -> ?
console.log(p2) // -> ?
  • 首先,函数传参是传递对象指针的副本;
  • 达到函数内部修改参数的属性这一步,p1的数值修改,age从25 -> 26
  • 若重新给person分配一个对象就出现了问题,如下图:
    在这里插入图片描述

所以最后 person 拥有了一个新的地址(指针),也就和 p1 没有任何关系了,导致了最终两个变量的值是不相同的。


4、类型判定

4.1、typeof

typeof对于原始类型来说,除了null都可以显示正确的类型,若想判定null的话可以使用过xxx === null

typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof 1n // bigint

typeof对于对象来说,除了函数都会显示object,所以说typeof并不能准确判定变量到底是什么类型。

typeof [] // 'object'
typeof {} // 'object'
typeof console.log // 'function'

4.2、instanceof

instanceof通过原型链的方式来判定是否构建函数的实例,一般用来判定具体的对象类型:

const Person = function() {}
const p1 = new Person()
p1 instanceof Person // true

var str = 'hello world'
str instanceof String // false

var str1 = new String('hello world')
str1 instanceof String // true

对于原始类型而言,instanceof直接判定类型不可以, 不过可以利用如下方法:

class PrimitiveString {
  static [Symbol.hasInstance](x) {
    return typeof x === 'string'
  }
}
console.log('hello world' instanceof PrimitiveString) // true

我们可能不知道 Symbol.hasInstance 是什么东西,其实就是一个能让我们自定义 instanceof 行为的东西,以上代码等同于 typeof 'hello world' === 'string',所以结果自然是 true 了。

这其实也侧面反映了一个问题:instanceof 并不是百分之百可信的。

// true
[].constructor === Array

4.3、Object.prototype.toString.call

Object.prototype.toString.call 综合来看是最佳选择,能判断的类型最完整,基本上是开源库选择最多的方式。
在这里插入图片描述


5、类型转换

JavaScript中存在三种情况:

  • 转换为bool
  • 转换为数字
  • 转换为字符串

在这里插入图片描述

注意:图中有一个错误,Boolean 转字符串这行结果我指的是 true 转字符串的例子,不是说 Boolean、函数、Symblo 转字符串都是 true

转Boolean:在条件判断时,除了 undefined, null, false, NaN, '', 0, -0,其他所有值都转为 true,包括所有对象。

5.1、对象转原始类型

对象在转换类型的时候,会调用内置的[[ToPrimitive]]函数,算法逻辑如下:

  • 若已经是原始类型,则不需要转换了;
  • 若需要转换的字符串就调用x.toString(),转换为基础类型的话就返回转换的数值,不是字符串类型的话就先调用valueOf,结果不是基础类型的话就调用toString
  • 调用x.valuof,若转换为了基础类型,就返回转换的数值;
  • 若都没有返回原始类型,则报错。

当然,可以选择重写Symbol.toPrimitive,这个方法可以在转原始类型的时候优先级最高。

let a = {
  valueOf() {
    return 0
  },
  toString() {
    return '1'
  },
  [Symbol.toPrimitive]() {
    return 2
  }
}
1 + a // => 3

6、四则运算符

加法运算符不同于其他几个运算符,它有以下几个特点:

  • 运算中其中一方为字符串,那么就会把另一方也转换为字符串
  • 如果一方不是字符串或者数字,那么会将它转换为数字或者字符串
1 + '1' // '11'
true + true // 2
4 + [1,2,3] // "41,2,3"
  • 对于第一行代码来说,触发特点一,所以将数字 1 转换为字符串,得到结果 '11'
  • 对于第二行代码来说,触发特点二,所以将true转为数字 1
  • 对于第三行代码来说,触发特点二,所以将数组通过 toString 转为字符串 1,2,3,得到结果 41,2,3

6.1、比较运算符

  • 若是对象,则通过toPrimitive转换对象
  • 若是字符串,则通过unicode字符索引来比较
let a = {
  valueOf() {
    return 0
  },
  toString() {
    return '1'
  }
}
a > -1 // true

在上述的代码中,a是对象,所以通过valueOf转换为原始类型在比较数值。


7、this

首先给出常见的this调用场景:

function foo() {
  console.log(this.a)
}
var a = 1
foo()

const obj = {
  a: 2,
  foo
}
obj.foo()

const c = new foo()
  • 对于直接调用foo而言,不管foo函数放在何处,this一定是window
  • 对于obj.foo而言,只要记住,谁调用了函数,谁就是this,所以这时候foo函数中的this指的就是obj对象;
  • 对于new的方式而言,this被永远绑定在了c上面,不会被任何方式改变this

给出JavaScript的箭头函数中的this

function a() {
  return () => {
    return () => {
      console.log(this)
    }
  }
}
console.log(a()()())
  • 首先箭头函数没有this,箭头函数的this只是取决于包裹箭头函数的第一个普通函数的this,在这个例子中,因为包裹箭头函数的第一个普通函数就是a,所以这时的this就是window另外箭头函数使用bind方法是无效的。
  • 另外一种情况就是bind这些改变上下文的API,this取决于第一个参数,若第一个参数空,则就是window

注意:若对一个函数进行多次bind,上下文表现如何?

let a = {}
let fn = function () { console.log(this) }
fn.bind().bind(a)() // => ?

也可以写作另一种形式:

let a = { name: 'yck' }
function foo() {
  console.log(this.name)
}
foo.bind(a)() // => 'yck'

以上就是bind的所有规则了,不同的规则之间根据优先级的高低来决定this的最终指向。

首先,new 的方式优先级最高,接下来是bind这些函数,然后是obj.foo()这种调用方式,最后是 foo 这种调用方式,同时,箭头函数的 this 一旦被绑定,就不会再被任何方式所改变。

总结如下图所示:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/174110.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue2基础、组件化编程、脚手架、Vuex、Vue路由、UI组件库

尚硅谷张天禹老师讲课 学习视频 1、Vue简介 Vue2中文官网 1.1 Vue 介绍 一套用于构建用户界面的渐进式JavaScript框架 构建用户界面:把数据通过某种办法变成用户界面渐进式:可以自底向上逐层的应用,简单应用只需要一个轻量小巧的核心库&…

SQL--DQL

目录 1、基础查询 1. 查询多个字段 1. 举例 2. 举例 2. 字段设置别名 1. 举例 2. 举例 3. 去除重复记录 1. 举例 2、条件查询 1. 等于&#xff08;&#xff09; 2. 小于&#xff08;<&#xff09; 3. 小于等于&#xff08;<&#xff09; 4. 没有&#xff…

Java设计模式中命令模式是怎么回事/命令模式如何使用,什么场景适用

继续整理记录这段时间来的收获&#xff0c;详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用&#xff01; 6.4 命令模式 6.4.1 定义 将一个请求封装为一个对象&#xff0c;使发出请求的责任和执行请求的责任分隔开&#xff0c;方便了将命令对象进行存储&#xff0c;传递…

激活函数(26个)

最近在学习网络&#xff0c;发现一会这个网络用了这个激活函数&#xff0c;一会那个网络用了那个激活函数&#xff0c;这些激活函数都有什么作用啊&#xff0c;不知道&#xff0c;这里学习一下&#xff0c;整理下来&#xff0c;方便以后查阅。 激活函数&#xff08;26个&#x…

Elasticsearch7.8.0版本高级查询——组合查询文档

目录一、初始化文档数据二、组合查询文档2.1、概述2.2、示例一、初始化文档数据 在 Postman 中&#xff0c;向 ES 服务器发 POST 请求 &#xff1a;http://localhost:9200/user/_doc/1&#xff0c;请求体内容为&#xff1a; {"name":"张三","age"…

ruoyi_cloud==启动

1-下载ruoyi_cloud源码&#xff0c;新建数据库 下载ruoyi_cloud源码&#xff0c; 新建数据库ry-config&#xff0c;并在数据库中执行ruoyi-cloud源码中ry_config_20220929.sql &#xff0c; 即导入若依这个项目的一些交给nacos管理的配置信息&#xff0c;后面nacos会来读取。…

[java/初学者]类的继承

前言 继承是OOP的三大特征之一&#xff0c; 它的作用是在现有类的基础上派生出一个新的类&#xff0c;这个类中继承了现有类的数据属性和行为&#xff0c;并且能进行扩展。 基于这一特性&#xff0c;我们将前者命名为“父类”或者“基类”&#xff0c;而后者则因此命名为“子…

【matplotlib】20.其他图

#【matplotlib】20.其他图 2023.1.20 polt为点线图&#xff0c;后面我们看看plt里面的其他图 20.1 Scatter 散点图 plt.scatter() import matplotlib.pyplot as plt import numpy as npn 1024x np.random.normal(0,1,n) y np.random.normal(0,1,n)# 颜色 这个应该是个tan值…

Java多线程02(生命周期,线程安全synchronized(),锁Lock )

目录1.线程的生命周期2.线程安全和同步代码块synchronized()3.Lock锁1.线程的生命周期 2.线程安全和同步代码块synchronized() synchronized(锁){ 操作共享数据的代码 }//保证线程安全 锁默认打开&#xff0c;有一个线程进去了&#xff0c;锁自动关闭。里面的代码全部执行完毕…

DFS(一)深度优先搜索(Depth First Search)一条道走到黑

目录 一、盒子与扑克牌 二、员工的重要性 三、图像渲染 一、盒子与扑克牌 假如有编号为1~3的3张扑克牌和编号为1~3的3个盒子&#xff0c;现在需要将3张牌分别放到3个盒子中去&#xff0c;且每个盒子只能放 一张牌&#xff0c;一共有多少种不同的放法。 当走到一个盒子面前的…

【Python-Django】医疗辅助平台-数据库设计-day2.1

操作需知&#xff1a; MySQL存储很长500的汉字选用字符类型_mysql字符串太长用什么存_信息时代弄潮儿的博客-CSDN博客 mysql中的Varchar(255)可以放多少个汉字_Ecloss的博客-CSDN博客_varchar255能存多少汉字 MySQL中的Text类型_SlowIsFastLemon的博客-CSDN博客_text类型 …

自制win10 PE usb启动盘教程

拿出祖传的U盘&#xff08;16GB&#xff09;安装老白菜根据教程制作U盘然后在U盘ios文件夹里面放入从系统之家下载的win10 ios文件包然后把U盘插入需要安装的电脑上面重启电脑按住F10打开BIOS设置界面USB启动设置为<启用>将UEFI和传统模式下的&#xff1a;U盘/USB硬盘USB…

【数据结构前言】

前言&#xff1a; 在之前我们已经有了C语言的基础&#xff0c;掌握了一些基本知识过后我们就可以进行其他方面的学习了&#xff0c;继我们学完C语言之后我们将会学习数据结构的相关知识&#xff0c;今天先让大家对其进行初步的认识&#xff01; 目录1. 什么是数据结构&#xff…

SpringCloud(13):分布式配置中心

1 为什么需要分布式配置中心&#xff1f; 在分布式系统中&#xff0c;由于服务数量巨多&#xff0c;为了方便服务配置文件统一管理&#xff0c;所以需要分布式配置中心组件。在Spring Cloud中&#xff0c;有分布式配置中心组件spring cloud confifig &#xff0c;它支持配置服…

增量式PID控制算法及仿真

当执行机构需要的是控制量的增量&#xff08;例如驱动步进电机&#xff09;时&#xff0c;应采用增量式PID控制。根据递推原理可得&#xff1a;增量式PID控制算法:根据增量式PID控制算法&#xff0c;设计了仿真程序&#xff0c;被控对象如下:PID控制参数:kp8&#xff0c;ki 0.1…

普中科技MicroPython基于esp32的基础教程-02

容器类型数据 序列 存放多值的连续内存空间&#xff0c;并且通过编号访问&#xff0c;其实就是类似于C语言的数组&#xff0c;相同数据类型、连续内存空间、使用下标访问 序列索引 支持正负操作&#xff0c;0到N&#xff0c;-N到-1 &#xff0c;但是C语言不支持负操作 个人觉…

温度、压力、物位仪表工作原理

温度、压力、物位仪表工作原理 一、温度仪表 1、温度仪表通常分一次仪表与二次仪表&#xff0c;一次仪表通常为&#xff1a;热电偶、热电阻、双金属温度计、就地温度显示仪等。二次仪表通常为温度记录仪、温度巡检仪、温度显示仪、温度调节仪、温度变送器等。 2、温度测量仪表…

Java基础进阶

Stream流 引例 需求&#xff1a;按照下面要求完成集合的创建和遍历 创建一个集合&#xff0c;存储多个字符串元素 1. 把所有以“曹”开头的元素存储到新集合中 2. 把曹开头&#xff0c;长度为3的元素存储到新集合中 List<String> list List.of("曹操", "…

【6s965-fall2022】剪枝✂pruningⅡ

剪枝比例 问题&#xff1a;我们应该如何找到每层的剪枝比率&#xff1f; 较浅的层&#xff0c;低层次的特征较深的层&#xff0c;抽象的特征 问题&#xff1a;哪些层的冗余度最高&#xff1f; 非统一剪枝&#xff08;每一层的稀疏度不一样&#xff09;比统一剪枝&#xff0…

python学习 --- 集合基础

目录 一、什么是集合&#xff1f; 二、集合的创建方式 1、直接使用{} 2、使用内置函数set() 三、集合的相关操作 1、集合元素的判断 2、集合元素的新增 3、集合元素的删除 四、集合间的关系 五、集合的数学操作 1、交集操作 2、并集操作 3、差集操作 4、对称差集…