image-20260123171141130

JavaScript 基础语法

开始本课程之前,建议先完成《HTML5 核心教程》《CSS3 核心教程》这两门前置课程,如果你只是想学习JavaScript的语法做Node.js后端开发,可以跳过前置课程,如果是前端Web学习路线务则必完成前置课程。

欢迎各位小伙伴来到前端路线的JavaScript课程,这一站也是前端三件套(HTML、CSS、JavaScript)中的最后一个,期待在这最后的旅途中与各位小伙伴一起进步!视频中所有的文档、资料,都可以直接在视频下方简介中找到,视频非培训机构出品,纯个人录制,不需要加任何公众号、小程序,直接自取即可。

教程开始之前,提醒各位小伙伴:

  • 如果你对某样东西不熟悉,请务必保证跟视频中使用一模一样的环境、一模一样的操作方式去使用,不要自作主张,否则出现某些奇怪的问题又不知道怎么办,就会浪费很多时间。
  • 在学习过程中,尽可能避免出现中文文件夹,包括后面的环境安装、项目创建,都尽量不要放在中文路径下(因为使用中文常常出现奇奇怪怪的问题)建议使用对应的英文单词代替,或者是用拼音都可以,最好只出现英文字母和数字。
  • 本系列教程统一使用 WebStorm 作为集成开发环境,该软件是免费使用的。
  • 请不要抱着应试教育的心态进行学习,学习编程开发是为了掌握技能,而不是单纯为了过考试。

如果觉得本视频对你有帮助,请一键三连支持一下UP主~

走进JavaScript

在前面的课程中,我们学习了HTML和CSS,我们已经知道,HTML是控制网页的整体框架结构,也就是用于表示页面上有些什么,怎么排列的,而CSS则是控制页面元素的外观,我们可以通过编写CSS来让网页上的元素变得更漂亮。而JavaScript,就像运行在浏览器上的程序一样,我们可以编写自己的程序逻辑来让网页展现出千变万化的效果。

它可以让我们的网页变成**“动态”**的。注意这里说的动态并非是让网页产生动画效果,而是指网页上的数据可以根据时间或状态动态变化:

  • 静态网页
    • 内容固定:网页内容在被编写时就已确定,存储为纯HTML文件(或包含简单CSS/JS),服务器直接返回预先生成的页面。
    • 无需服务器动态处理:用户请求时,服务器直接将文件发送给浏览器,内容不会随用户行为、数据变化或时间动态更新。
    • 示例:企业官网的“关于我们”页、纯HTML博客文章。
  • 动态网页
    • 内容可实时生成:页面内容由服务器根据用户请求、数据库数据、时间或其他条件动态生成。
    • 依赖服务器端处理:服务器会执行代码(如PHP、Python、Node.js等),从数据库或其他数据源获取数据,动态拼接成HTML后返回给浏览器。
    • 示例:电商网站商品列表(根据搜索条件实时加载)、在线论坛帖子(用户发布后动态展示)、社交媒体动态更新。

实际上,我们在生活中访问的绝大多数网站都是动态网站,页面上的数据无时无刻都在更新,比如淘宝网上的商品,抖音上的视频,微博上的帖子等等。除此之外,JavaScript还能让我们与页面进行各种交互操作,比如点击卡片弹出消息,按下键盘播放动画等。

这一节,我们就来认识一下JavaScript,看看它到底有什么魔力。

计算机编程语言

考虑到各位小伙伴可能还未接触过任何一门编程语言,这里先科普一下什么是编程语言。

计算机虽然名字听着很高级,不过它也是由一个个简单电路组成的:

image-20230228214034266

这是我们在初中就学习过的电路图,不过这种电路太过简单,只能完成一些很基础的的操作,比如点亮小灯泡等。很明显,想要实现计算机这么高级的运算机器,肯定是做不到的,这时我们就需要引入更加强大的数字电路了。

用数字信号完成对数字量进行算术运算逻辑运算的电路称为数字电路,或数字系统。由于它具有逻辑运算和逻辑处理功能,所以又称数字逻辑电路。现代的数字电路由半导体工艺制成的若干数字集成器件构造而成,逻辑门是数字逻辑电路的基本单元

计算机专业一般会在大一开放《数字电路》这门课程,会对计算机底层的数字电路实现原理进行详细介绍。

数字电路中,用电压的高低来区分出两种信号,低电压表示0,高电压表示1,由于只能通过这种方式表示出两种类型的信号,所以计算机采用的是二进制。二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”。

比如我们一般采用的都是十进制表示,比如9再继续加1的话,就需要进位了,变成10,在二进制中,因为只有0和1,所以当1继续加1时,就需要进位了,就变成10了(注意这不是十,读成一零就行了)

CPU是电脑的核心,用于执行我们给到它的各种指令,不过,由于计算机底层只能识别二进制信号,我们发送给CPU的所有指令都必须变成二进制的形式,比如:000001 - 代表开机、000010 - 代表关机、000011 - 代表进行加法运算(随便瞎编的,实际比这个复杂得多)当我们通过电路发送给CPU这样的二进制指令,CPU就能够根据我们的指令执行对应的任务,并通过电路输出执行的结果,同样也是二进制的,这其实就是机器语言

不过随着时代的进步,指令集越来越大,CPU支持的运算类型也越来越多,这样的纯二进制编写指令运行程序实在是太累了。因此,一些编程语言就出现了,从最初的汇编(低级语言)到现在的C、C++、Go、Rust、Java、Python、Swift等等,都是编程语言,这些语言可以采用一种更加接近我们人类自然语言的语法进行编写,并将我们编写的代码自动转换为机器可以识别的二进制指令,从而让我们可以以更简单的方式操作计算机进行运算。

截止2025年8月当下比较热门的编程语言排名:

image-20260123181416085

不过,这里需要区分一下什么是编译型语言什么是解释型语言:

  • 编译型语言: 编译器在代码运行前把整个程序一次性翻译成机器码(例如 main.c 被编译成 main.exe) 直接供硬件执行。
  • 解释型语言: 依赖解释器逐行读取代码,每读一条就翻译成机器指令,直接给硬件执行(类似“同声传译”)更加灵活,无需编译就能直接运行。

而我们要学习的JavaScript就是解释型语言,由浏览器(内部的JavaScript引擎)对代码进行解释执行,从而让CPU进行各种运算。

现代 JavaScript 执行环境(如 V8 引擎)中也融入了一些编译优化机制,会自动编译一些代码为机器码,使得其执行过程更接近“即时编译(JIT)”,但这并不改变其核心的“解释型”本质。

JavaScript的由来

JavaScript(简称JS)是一种广泛使用的脚本语言,主要用于Web开发,同时也在其他领域(如后端、移动应用、数据库等)获得了广泛应用。它的发展历程充满了传奇色彩,从最初的简单脚本发展到如今强大的全栈语言。

20世纪90年代初,互联网刚刚兴起,网页主要是静态的,缺乏交互性。网景通讯公司(Netscape)的工程师 布兰登·艾克(Brendan Eich) 被要求开发一种能让网页**“活”起来的脚本语言**,用于与服务器端交互和处理用户操作。1995年,为了借助当时热门的Java语言做营销,这门新的脚本语言被命名为“JavaScript”(但语法与Java几乎无关)

1995年,布兰登·艾克在短短10天内设计并实现了最初的JavaScript引擎,命名为 LiveScript(后改名为JavaScript),随Netscape 2.0发布,提供了基础的语法和浏览器DOM操作(如alert()、变量、函数等),微软随后推出了IE3.0,内置了名为 JScript 的JavaScript克隆版本,网景则与Sun Microsystems合作推动标准化。这也导致了早期语言特性的分化。t

1997年,ECMA国际(ECMA-262)发布了ECMAScript规范,确立了JavaScript的基础语法,奠定了跨浏览器兼容性的基础。

1998年,W3C推出了第一个DOM标准(Document Object Model),JS开始能更便捷地操作网页结构和样式(如动态创建元素、绑定元素事件)

2005年,Google的Gmail和AdSense大规模应用了AJAX技术(Asynchronous JavaScript and XML),JavaScript通过XMLHttpRequest实现异步数据交互,彻底改变了Web体验。此时,JS从“网页点缀”升级为网页核心交互语言。

2006年,JQuery框架横空出世,以“写得更少,做得更多”著称,简化了DOM操作、事件绑定和动画,成为当时全球最流行的JS库。

2013年,React框架推出,引入虚拟DOM和组件化思想,推动了前端开发模式的革新,让复杂交互应用(如Facebook、Instagram)成为可能。

2014年,更加轻量级、入门友好,快速上手的Vue框架推出,在国内开发者中备受欢迎。

2015年,ECMAScript 2015(ES6)引入了箭头函数、let/const、模块系统(import/export)、Promise、类(Class)等,语言能力大幅提升。后续ES7至今持续迭代,增加更多新特性,如Optional Chaining?.)、Async/Await等,使代码更简洁强大。

ECMAScript是规则,JavaScript是在该规则下运行的具体实现(如V8引擎为JavaScript提供执行环境),两者经常被混淆但本质不同,就像"HTML规范"和"网页渲染实现"的关系。在日常开发中,通常默认将"JavaScript"理解为ECMAScript规范支持的全栈语言。

在页面中引入JavaScript

前面我们介绍了什么是编程语言,什么是JavaScript,这一节我们来看看如何在页面中引入JavaScript脚本。

和CSS一样,如果想要在HTML中引入JavaScript有多种的方式:

  • **内部JavaScript标签:**编写在HTML内的JavaScript代码,和HTML代码一起存在。
  • **外部JavaScript文件:**独立编写的外部JS文件,可以单独引入。
  • **元素事件JavaScript标签:**直接在HTML标签的事件属性中嵌入JavaScript代码。

这与CSS的三种引入方式非常类似,我们来看看如何操作。首先是最简单的一种内部JavaScript标签,我们可以将其写到HTML文档的任何位置,只要此区域被浏览器加载就会自动执行其中的JavaScript代码。我们可以先试试看写到head标签内,这样

html 复制代码
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script>
    alert('Hello, World!')
  </script>
</head>

这里使用的alert是一个JS函数,可以实现页面通知效果,当我们在浏览器打开页面之后会立即收到一个通知。

此外,我们也可以将其放到body的任何位置:

html 复制代码
<body>
  <div>我是页面上的一段普通内容</div>
  <script>
      alert('Hello, World!')
  </script>
</body>

无论放到哪个位置,JS代码都会自动执行,不过,不同的位置会存在一些加载顺序上的区别,我们会在后续DOM章节中为大家详细介绍在不同位置产生的效果。

除了直接在HTML中编写JS代码,我们也可以将其放到一个独立的文件中再单独引入,存放JavaScript代码的文件以.js结尾,我们可以直接在里面写入测试的代码:

js 复制代码
alert('Hello, World!');

然后通过script标签引入:

html 复制代码
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="js/script.js"></script>
</head>

和之前一样,无论是直接编写的内部JS代码还是外部引入的JS文件,都可以插入到页面的任意位置上,只要页面加载就会自动执行。

第三种方式比较特殊,HTML存在多种元素事件,比如当我们点击某个div标签时,就会触发点击事件,当我们滚动窗口时,就会触发页面的滚动事件,当触发这些事件时,我们可以在HTML标签中增加对于这些事件的处理逻辑,而具体的操作就需要使用JavaScript来进行编写,这里以onclick为例:

html 复制代码
<body>
  <div onclick="alert('我是页面上的一段普通内容')">我是页面上的一段普通内容</div>
</body>

我们可以尝试点击这个盒子,触发点击事件后也会执行JS代码。有关HTML元素事件,我们会在后续的DOM章节中为大家详细介绍。

介绍完三种JS代码引入方式之后,我们需要额外介绍一个标签,叫做noscript,这个标签表示的是在浏览器未开启或不支持JavaScript功能时需要展示的内容,一些比较老旧或是软件内嵌的的浏览器可能未开启JS功能,此时这个标签就非常有用了:

html 复制代码
<body>
  <div>我是页面上的一段普通内容</div>
  <noscript>请启用JavaScript以获得最佳体验</noscript>
</body>

我们可以通过手动关闭JS功能来模拟一下,打开开发者工具的设置按钮:

image-20260123235319009

接着往下滑找到停用JavaScript选项:

image-20260123235406537

接着刷新页面之后,我们就会发现原本应该自动执行的JS脚本不会自动执行,并且页面上出现了我们刚刚设置的noscript标签中的内容:

image-20260123235455334

在浏览器中直接测试

有些时候,我们可能并不想为了测试一两行代码而专门去创建一个 HTML 文件。这时候,利用浏览器自带的 开发者工具(Developer Tools)进行直接测试是最方便的选择。

大多数现代浏览器(如 Chrome, Edge, Firefox, WebStorm 内置浏览器)都提供了强大的控制台功能:

  1. 打开方式:在浏览器页面中按下 F12 键,或者右键点击页面选择“检查”,然后切换到 **Console(控制台)**选项卡。
  2. 交互式执行:在控制台的光标处,你可以直接输入 JavaScript 代码并按 Enter 键运行。例如,输入 console.log("Hello JS")1 + 1,它会立即返回结果。
  3. 多行输入:如果你想编写一段较长的逻辑,可以按 Shift + Enter 进行换行,而不是直接执行。
image-20260123235857398

我们可以直接在控制台输入一段JS代码,然后敲击回车就可以执行了:

image-20260124000000274

这在需要临时测试一些JS代码的情况下非常好用,后续我们会尝试使用这种方式来直接调试页面中已经存在的JS代码。

学会在Chrome中控制台调试JS代码,这是你即将成为一名合格前端开发的第一步,如果你运气好的话,说不定还能获得一枚 Google Developer Program的"Chrome DevTools User"徽章!

除了在浏览器中直接测试外,我们也可以在WebStorm中直接运行,但是注意需要安装NodeJS/Deno/Bun其中一种环境。

至此,有关JavaScript的基础介绍就结束了,接下来我们就开始正式学习一下JavaScript的语法。

JavaScript入门

这一节我们将从最简单的变量声明开始,逐步介绍JavaScript的语法。

注释

和前面HTML、CSS一样,我们可以在JS中编写注释内容,来为某段代码进行解释,以便于我们后续能够快速回顾这段代码的目的。在JS中创建注释非常简单,首先是最基础的单行注释:

js 复制代码
// 这段代码是用于发出通知,并展示Hello World
alert('Hello, World!')

单行注释使用//进行表示,后续只要不出现换行的文本都属于注释内容,不会参与到实际的程序执行中。

此外,还有一种方式和CSS是一样的,我们可以使用:

js 复制代码
/* 这段代码是用于发出通知,并展示Hello World */
alert('Hello, World!')

这种写法在JS中叫做多行注释,我们可以编写很多行文本内容作为注释:

js 复制代码
/* 
这段代码是用于发出通知
并展示Hello World
*/
alert('Hello, World!')

还有一种看起来更加规范一点的多行注释:

js 复制代码
/**
 * 这段代码是用于发出通知
 * 并展示Hello World
 */
alert('Hello, World!')

不过这种注释更多用于后续函数声明的解释中,我们会在后续内容中继续介绍。

变量与常量

我们的程序不可能永远都只进行上面那样的简单通知操作,有些时候可能需要计算某些数据,此时我们就需要用到变量了。

那么,什么是变量呢?我们在数学中其实已经学习过变量了:

变量,指值可以变的量。变量以非数字的符号来表达,一般用拉丁字母。变量的用处在于能一般化描述指令的方式。结果只能使用真实的值,指令只能应用于某些情况下。变量能够作为某特定种类的值中任何一个的保留器。

比如一个公式 x^2+6=16+6=22 此时x就是一个变量,变量往往代表着某个值,比如这里的x就代表的是4这个值。在JavaScript中,我们也可以让变量去代表一个具体的值,并且变量的值是可以发生变化的。

要声明一个变量,我们需要使用以下格式:

js 复制代码
var [变量名称]

这里的变量名称不能随便起,需要遵循以下规则:

  1. 变量名可以由字母、数字、下划线或美元符$组成,但是不能以数字开头(虽然直接写中文也可以,但是不推荐)
  2. 变量名不能为系统关键字或保留字,比如上面的var就是一个关键字,有关JS的更多关键字,我们会在后续学习中逐步认识。
  3. 应该使用有意义的名称,达到见名知意的目的(我们一般采用英文单词)最好以小写字母开头。

当然各位小伙伴没必要刻意去进行记忆,我们会在学习的过程中逐步认识到这些关键字。新手要辨别一个单词是否为关键字,只需要通过WebStorm的高亮颜色进行区分即可,比如:

image-20260124002950027

深色模式下,关键字会高亮为橙色,浅色模式下会高亮为深蓝色,普通的代码都是正常的灰白色。这里我们写了一个变量a,但是这个变量一开始没有任何值,比如现在我们要让这个变量表示10,那么就可以将10赋值给这个变量:

js 复制代码
var a = 10

只需要使用等号就可以为变量设定一个初始值,也可以叫做赋值操作,此时,变量a就代表10这个数字了。

我们可以使用console.log来打印某个变量的值或函数执行的结果,它是 JavaScript 中最常用的调试工具,本质是一个函数调用(有关函数的创建和使用我们会在下一章详细介绍)用于在浏览器控制台Node.js 终端中输出信息,帮助开发者查看程序运行过程中的变量值、状态变化、错误提示等:

js 复制代码
/* 注意存在多行代码时,程序会从上往下执行,注意每一句代码一定要换行 */
var a = 10
console.log(a)
image-20260124003331884

可以看到,在控制台中成功输出了变量a的值,并且在控制台的右边会显示这一次输出是哪里进行的。这里的script.js:2表示是这个JS文件执行到第二行的代码打印的结果。

除了在创建变量时给于初始值,我们也可以在后续的代码中设置变量的值:

js 复制代码
var a
a = 20  //通过等号为变量a赋值为20
console.log(a)

注意如果存在多次赋值操作,那么最后一次的执行结果才是a的最终值:

js 复制代码
var a
a = 20
a = 30  //这里再次进行了一次赋值操作,使得a变成了30
console.log(a)

除了简单的赋值,我们还可以使用数学中的加减乘除运算来实现更多效果,比如:

js 复制代码
var a = 1 + 2  //让a获得1+2的值
console.log(a)  //得到3
js 复制代码
var a = 10   //让a初始等于10
a = a + 8  //让a等于当前a的值加上8
console.log(a)  //得到18
js 复制代码
var a = 10   //让a初始等于10
a = a - 5  //让a等于当前a的值减去5
console.log(a)  //得到5
js 复制代码
var a = 10   //让a初始等于10
a = a * a  //让a等于当前a的值乘以a
console.log(a)  //得到100
js 复制代码
var a = 10   //让a初始等于10
a = a / 2  //让a等于当前a的值除以2
console.log(a)  //得到5

我们还可以一次性创建多个变量,可以逐行编写或是用逗号分割连续编写:

js 复制代码
var a = 10, b = 9  //使用逗号分割可以在一行写多个变量
console.log(a)

多个变量之间也是可以互相进行运算的:

js 复制代码
var a = 10, b = 9
a = a + b + 10  //让a等于a当前值加上b的值再加上10
console.log(a)  //得到29
js 复制代码
var a = 10, b = 9
console.log(a - b)  //直接打印a - b的值

有关更多运算相关的知识点,我们会在后续章节中专门介绍,这里仅做了解即可。

在了解完变量之后,相信各位小伙伴一个对于编程有了一个新的认识,有了变量我们就可以做更多好玩的事情了。只不过这里需要补充一个非常重要的知识点,不知道各位小伙伴是否有注意到WebStorm中的黄标:

image-20260124011244965

为什么WebStorm不推荐我们使用呢?这是因为var 关键字在声明变量时存在一些历史遗留问题和容易引发错误的特性,因此 ES6 及后续标准更推荐使用 letconst 来替代 var,以下是不推荐使用 var 的主要原因:

  1. var 声明的变量存在变量提升(Hoisting)特性,即变量声明会被提升到其作用域的顶部,但赋值不会提升。
  2. var 声明的变量属于其所在的函数作用域(或全局作用域),而非块级作用域。
  3. 在同一作用域内使用 var 重复声明变量时,不会报错,而是直接覆盖已有变量的值,这会导致逻辑错误。
  4. var无法定义一个不可修改的变量,也就是我们下面马上要提到的常量。

因此,我们更推荐大家使用let关键字来声明变量,它很好地解决了var导致的一些问题,后续课程中我们也会使用let进行讲解,不再使用var关键字声明变量。变量使用let关键字来声明,效果和之前是一样的:

js 复制代码
let a = 10, b = 9
console.log(a - b)

介绍完变量,我们接着来介绍一下常量,有时候我们希望变量的值一直保持不变,我们就可以将其指定为常量,这里我们介绍一下const关键字,它可以用于声明一个常量:

js 复制代码
const a = 10
console.log(a)

看上去和之前讲解的变量没有任何区别,我们可以尝试去修改它的值:

js 复制代码
const a = 10
a = 20   //会发生报错
console.log(a)  //这里不会执行
image-20260124011607651

此时浏览器控制台出现了一段红色的错误信息:Assignment to constant variable.,表示我们在为一个常量进行赋值操作,这是不允许的,所以浏览器直接出现了一段报错,并且出现报错后,由于程序发生问题,后续的JS代码也没有继续执行了。

所以,和变量不同的是,常量必须存在默认赋值,并且值一旦确定,后续就不可进行修改,因此,我们一般将那些声明后不会再发生改变的变量设置为常量,后续可能会出现变化的设置为变量。

虽然常量不可变化,但是我们也可以将其加入到运算中:

js 复制代码
const a = 20
let b = 5, c = 10
c = b + a - 2
console.log(c)

这里还需要提及一下,我们也可以直接在控制台中访问已经加载执行的JS代码,包括其中声明的变量或函数:

image-20260124012256698

可能会有小伙伴注意到,这里的VM653:1其实是一个虚拟环境,VM 代表“Virtual Machine”,Chrome 会为动态注入的脚本、扩展程序、或 eval 执行的代码创建一个独立的“沙箱环境”或“虚拟上下文”,这些代码会被临时分配一个唯一的 VM 编号,比如我们这里手动在控制台执行的JS代码就是动态插入的调试代码,不像上面的结果那样显示具体的JS文件或HTML文件代码位置。

最后要注意的是,无论是变量还是常量,一旦创建之后是不允许重复创建的,否则浏览器会出现标识符已声明错误:

image-20260124141103424

var声明的变量则不受限制,但这很容易导致一些逻辑上的错误,因此不建议使用。

计算机中的二进制(选学)

在计算机中,所有的内容都是二进制形式表示。十进制是以10为进位,如9+1=10;二进制则是满2进位(因为我们的计算机是电子的,电平信号只有高位和低位,你也可以暂且理解为通电和不通电,高电平代表1,低电平代表0,由于只有0和1,因此只能使用2进制表示我们的数字!)比如1+1=10=2^1+0,一个位也叫一个bit,8个bit称为1字节,16个bit称为一个字,32个bit称为一个双字,64个bit称为一个四字,我们一般采用字节来描述数据大小。

111 = 7

注意这里的bit跟我们生活中的网速MB/s是不一样的,小b代表的是bit,大B代表的是Byte字节(8bit = 1Byte字节),所以说我们办理宽带的时候,100Mbps这里的b是小写的,所以说实际的网速就是100/8 = 12.5 MB/s了。

十进制的7 -> 在二进制中为 111 = 2^2 + 2^1 + 2^0

现在有4个bit位,最大能够表示多大的数字呢?

  • 最小:0000 => 0
  • 最大:1111 => 23+22+21+20 => 8 + 4 + 2 + 1 = 15

在Java中,无论是小数还是整数,他们都要带有符号(和C语言不同,C语言有无符号数)所以,首位就作为我们的符号位,还是以4个bit为例,首位现在作为符号位(1代表负数,0代表正数):

  • 最小:1111 => -(22+21+2^0) => -7
  • 最大:0111 => +(22+21+2^0) => +7 => 7

现在,我们4bit能够表示的范围变为了-7~+7,这样的表示方式称为原码。虽然原码表示简单,但是原码在做加减法的时候,很麻烦!以4bit位为例:

1+(-1) = 0001 + 1001 = 怎么让计算机去计算?(虽然我们知道该去怎么算,但是计算机不知道!)

我们得创造一种更好的表示方式!于是我们引入了反码

  • 正数的反码是其原码本身
  • 负数的反码是在其原码的基础上, 符号位不变,其余各个位取反

经过上面的定义,我们再来进行加减法:

1+(-1) = 0001 + 1110 = 1111 => -0 (直接相加,这样就简单多了!)

思考:1111代表-0,0000代表+0,在我们实数的范围内,0有正负之分吗?0既不是正数也不是负数,那么显然这样的表示依然不够合理!根据上面的问题,我们引入了最终的解决方案,那就是补码,定义如下:

  • 正数的补码就是其本身 (不变!)
  • 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1(即在反码的基础上+1,此时1000表示-8)
  • 对补码再求一次补码就可得该补码对应的原码。

比如-7原码为1111,反码为1000,补码就是1001了,-6原码为1110,反码为1001,补码就是1010。所以在补码下,原本的1000就作为新增的最小值-8存在。

所以现在就已经能够想通,-0已经被消除了!我们再来看上面的运算:

1+(-1) = 0001 + 1111 = (1)0000 => +0 (现在无论你怎么算,也不会有-0了!)

所以现在,1111代表的不再是-0,而是-1,相应的,由于消除-0,负数多出来一个可以表示的数(1000拿去表示-8了),那么此时4bit位能够表示的范围是:-8~+7(Java使用的就是补码!)在了解了计算机底层的数据表示形式之后,我们再来学习这些基本数据类型就会很轻松了。

正在加载页面,请稍后...