JS 入门教程-JS基础

71 阅读1小时+

0. 计算机编程基础

能够说出什么是编程语

能够区分编程语言和标记语言的不同

能够说出常见的数据存储单位及其换算关系

能够说出内存的主要作用及特点

编程语言

编程

  • 编程:就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。

  • 计算机程序:就是计算机所执行的一系列的指令集合,而程序全部都是用我们所掌握的语言来编写的,所以人们要控制计算机一定要通过计算机语言向计算机发出命令。

  • 从事编程的人员,就是程序员。 但是一般程序员都比较幽默,为了形容自己的辛苦工作,也成为“码农”,或者 “程序猿”/ “程序媛”

注意:上面所定义的计算机指的是任何能够执行代码的设备,可能是智能手机、ATM机、黑莓PI、服务器

等等。

计算机基础

计算机语言指用于人与计算机之间通讯的语言,它是人与计算机之间传递信息的媒介。

计算机语言的种类非常的多,总的来说可以分成机器语言汇编语言高级语言三大类。

实际上计算机最终所执行的都是 机器语言,它是由“0”和“1”组成的二进制数,二进制是计算机语言的基础

image.png

编程语言

可以通过类似于人类语言的 ”语言”来控制计算机,让计算机为我们做事情,这样的语言就叫做编程语言(ProgrammingLanguage)。

编程语言是用来控制计算机的一系列指令,它有固定的格式和词汇(不同编程语言的格式和词汇不一样),必须遵守。

如今通用的编程语言有两种形式:汇编语言和高级语言。

  • 汇编语言和机器语言实质是相同的,都是直接对硬件操作,只不过指令采用了英文缩写的标识符,容易识别和记忆。

  • 高级语言主要是相对于低级语言而言,它并不是特指某一种具体的语言,而是包括了很多编程语言,常用的有C语言、C++、Java、C#、Python、PHP、JavaScript、Go语言、Objective-C、Swift等。

image.png

翻译器

高级语言所编制的程序不能直接被计算机识别,必须经过转换才能被执行,为此,我们需要一个翻译器。

翻译器可以将我们所编写的源代码转换为机器语言,这也被称为二进制化。 记住1和 0。

image.png

编程语言和标记语言区别
  • 编程语言有很强的逻辑和行为能力。在编程语言里, 你会看到很多 if else 、for 、while等具有逻辑性和行为能力的指令,这是主动的。
  • 标记语言(html)不用于向计算机发出指令,常用于格式化和链接。标记语言的存在是用来被读取的, 他是被动的。

总结

  1. 计算机可以帮助人类解决某些问题
  2. 程序员利用编程语言编写程序发出指令控制计算机来实现这些任务
  3. 编程语言有机器语言、汇编语言、高级语言
  4. 高级语言需要一个翻译器转换为计算机识别的机器语言
  5. 编程语言是主动的有很强的逻辑性

计算机基础

计算机组成

image.png

数据存储

  1. 计算机内部使用二进制 0 和 1来表示数据。

  2. 所有数据,包括文件、图片等最终都是以二进制数据(0 和 1)的形式存放在硬盘中的。

  3. 所有程序,包括操作系统,本质都是各种数据,也以二进制数据的形式存放在硬盘中。平时我们所说的安

装软件,其实就是把程序文件复制到硬盘中。

  1. 硬盘、内存都是保存的二进制数据

数据存储单位

bit < byte < kb < GB < TB<.....

  • 位(bit): 1bit 可以保存一个 0 或者 1 (最小的存储单位)
  • 字节(Byte):1B = 8b
  • 千字节(KB):1KB = 1024B
  • 兆字节(MB):1MB = 1024KB
  • 吉字节(GB): 1GB = 1024MB
  • 太字节(TB): 1TB = 1024GB
  • ...

程序运行

image.png

  1. 打开某个程序时,先从硬盘中把程序的代码加载到内存中

  2. CPU执行内存中的代码

注意:之所以要内存的一个重要原因,是因为 cpu 运行太快了,如果只从硬盘中读数据,会浪费cpu性能,所

以,才使用存取速度更快的内存来保存运行时的数据。(内存是电,硬盘是机械)

1. 初识JavaScript

1. 初识 JavaScript

1. JavaScript 是什么

1. 谁开发的?
  • 布兰登·艾奇(Brendan Eich,1961年~)。
  • 神奇的大哥用10天完成 JavaScript 设计。
  • 最初命名为 LiveScript,后来在与 Sun 合作之后将其改名为 JavaScript。
2. JavaScript (是什么?)
  • JavaScript 是一种运行在客户端(浏览器)的编程语言(也可以说是脚本语言,Script 是脚本的意思),可以实现很多的网页交互效果。
  • 脚本语言:不需要编译,运行过程中由 js 解释器( js 引擎)逐行来进行解释并执行
  • 现在也可以基于 Node.js 技术进行服务器端编程

为了阅读方便,我们后面把JavaScript 简称为 JS。

2. JavaScript 的作用(做什么)
  • 网页特效 (监听用户的一些行为让网页作出对应的反馈)
  • 表单验证(针对表单数据的合法性进行判断) (JS 产生最初的目的)
  • 数据交互 (获取后台的数据, 渲染到前端)
  • 服务端编程(Node.js)
  • 桌面程序(Electron)
  • App(Cordova)
  • 控制硬件-物联网(Ruff)
  • 游戏开发(cocos2d-js)
3. JS 的组成(有什么?)

image.png

ECMAScript
  • ECMAScript 规定了js基础语法核心知识。

    比如:变量、分支语句、循环语句、对象等等。

  • ECMAScript 是由ECMA 国际(原欧洲计算机制造商协会)进行标准化的一门编程语言,这种语言在万维网上应用广泛,它往往被称为 JavaScript 或 JScript,但实际上后两者是 ECMAScript 语言的实现和扩展。(了解)

  • ECMAScript:是所有浏览器厂商共同遵守的一套JS语法工业标准。(了解)

image.png 更多参看MDN: developer.mozilla.org/zh-CN/docs/…

Web APIs
  • DOM:文档对象模型(Document Object Model,简称DOM),操作文档,比如对页面元素进行移动、大小、添加删除等操作

    DOM 是W3C组织推荐的处理可扩展标记语言的标准编程接口。(了解)

  • BOM ——浏览器对象模型(Browser Object Model,简称BOM)操作浏览器,比如页面弹窗,检测窗口宽度、存储数据到浏览器等等

    它提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等。(了解)

4. 小结
  • JavaScript是什么? JavaScript 是一种运行在客户端(浏览器)的编程语言
  • JavaScript组成是什么?ECMAScript( 基础语法 )、web APIs (DOM、BOM)

2. JavaScript 书写位置

JS 有3种书写位置,分别为行内、内部(内嵌)和外部。

image.png

内部(内嵌) JS

直接写在html文件里,用script标签包住

规范:script标签写在</body>上面

注意事项:

我们将 <script> 放在HTML文件的底部附近的原因是浏览器会按照代码在文件中的顺序加载 HTML。

如果先加载的 JavaScript 期望修改其下方的 HTML,那么它可能由于 HTML 尚未被加载而失效。

因此,将 JavaScript 代码放在 HTML页面的底部附近通常是最好的策略。

<script>
    alert('Hello World~!');
</script>
  • 内嵌 JS 是学习时常用的方式
外部 JS

代码写在以.js结尾的文件里

语法:通过script标签,引入到html页面中。

注意事项:

  1. script标签中间无需写代码,否则会被忽略!
  2. 外部JavaScript会使代码更加有序,更易于复用,且没有了脚本的混合,HTML 也会更加易读,因此这是个好的习惯。
<script src="my.js"></script>
  • 适合于JS 代码量比较大的情况
内联(行内) JS

代码写在标签内部

<input type="button" value="点我试试" onclick="alert('Hello World')" />
  • 可以将单行或少量 JS 代码写在HTML标签的事件属性中(以 on 开头的属性),如:onclick
  • 注意单双引号的使用:在HTML中我们推荐使用双引号, JS 中我们推荐使用单引号
  • 可读性差, 在html中编写JS大量代码时,不方便阅读;
  • 引号易错,引号多层嵌套匹配时,非常容易弄混;
  • 特殊情况下使用
小结
  1. JavaScript三种书写位置?内部、外部、行内

  2. 注意事项:

  • 书写的位置尽量写到文档末尾 前面
  • 外部 js 标签中间不要写代码,否则会被忽略

3. JavaScript 注释

为了提高代码的可读性,JS与CSS一样,也提供了注释功能。JS中的注释主要有两种,分别是单行注释和块注释(多行注释)。

单行注释

符号: //

作用://右边这一行的代码会被忽略

快捷键:ctrl + /

多行注释

符号: /* */

作用:在/* 和 */ 之间的所有内容都会被忽略

快捷键:shift + alt + A

了解:

快捷键修改为: ctrl + shift + /

修改方式: vscode -> 首选项按钮 -> 键盘快捷方式 -> 查找 原来的快捷键 -> 修改为新的快捷键 -> 回车确认

4. JavaScript 的结束符

  • 作用: 使用英文的 ; 代表语句结束
  • 实际情况: 实际开发中,可写可不写, 浏览器(JavaScript 引擎) 可以自动推断语句的结束位置
  • 现状: 在实际开发中,越来越多的人主张,书写 JavaScript 代码时省略结束符
  • 约定:为了风格统一,结束符要么每句都写,要么每句都不写(按照团队要求)

image.png

image.png

5. JavaScript 输入输出语法

什么是语法?

人和计算机打交道的规则约定

我们要按照这个规则去写

比如: 你吃了吗?

我们程序员需要操控计算机,需要计算机能看懂

输出和输入也可理解为人和计算机的交互,用户通过键盘、鼠标等向计算机输入信息,计算机处理后再展示结果给用户,这便是一次输入和输出的过程。

  • 输出语法
    • 语法1:document.write('要出的内容')

      作用:向body内输出内容

      注意:如果输出的内容写的是标签,也会被解析成网页元素

    • 语法2:alert('要出的内容')

      作用:页面弹出警告对话框

    • 语法3:console.log('控制台打印')

      作用:控制台输出语法,程序员调试使用

  • 输入语法
    • 语法:prompt('请输入您的名字')

      作用:显示一个对话框,对话框中包含一条文字信息,用来提示用户输入文字

      展示:image.png

JavaScript 代码执行顺序:

按HTML文档流顺序执行JavaScript代码

alert() 和 prompt() 它们会跳过页面渲染先被执行(目前作为了解,后期讲解详细执行过程)

6. 字面量

在计算机科学中,字面量(literal)是在计算机中描述 事/物。(字面量是在源代码中一个固定值的表示法,通俗来说,就是字面量表示如何表达这个值。)

比如:

  • 我们工资是: 1000 此时 1000 就是 数字字面量
  • '黑马程序员' 字符串字面量
  • 还有接下来我们学的 [] 数组字面量 {} 对象字面量 等等

7. HTML/CSS/JS 的关系

image.png

8. 浏览器执行 JS 简介

浏览器分成两部分:渲染引擎和 JS 引擎

  • 渲染引擎:用来解析HTML与CSS,俗称内核,比如 chrome 浏览器的 blink ,老版本的 webkit
  • JS 引擎:也称为 JS 解释器。 用来读取网页中的JavaScript代码,对其处理后运行,比如 chrome 浏览器的 V8

注意:浏览器本身并不会执行JS代码,而是通过内置JavaScript 引擎(解释器) 来执行 JS 代码 。JS 引擎执行代码时逐行解释

每一句源码(转换为机器语言),然后由计算机去执行,所以 JavaScript 语言归为脚本语言,会逐行解释执行。

image.png

小结

  1. JavaScript是什么?

    JavaScript 是一种运行在浏览器的编程语言,可以实现很多的网页交互效果。

  2. JavaScript 书写位置?

    行内 JavaScript

    内部 JavaScript – 写到 </body> 标签上方

    外部 JavaScript - 但是 <script> 标签不要写内容,否则会被忽略

  3. JavaScript 的注释?

    单行注释 //

    多行注释 /* */

  4. JavaScript 的结束符?

    分号; 可以加也可以不加,可以按照团队约定

  5. JavaScript 输入输出语句?

    输入: prompt()

    输出: alert() document.write() console.log()

2. 变量

image.png

1. 变量概述

什么是变量

白话:变量就是一个装东西的盒子。

通俗:变量是计算机中用来存储数据的容器,它可以让计算机变得有记忆。

image.png

注意:变量不是数据本身,它们仅仅是一个用于存储数值的容器。可以理解为是一个个用来装东西的纸箱子

总结:

  1. 变量是怎么理解?

    计算机中用来存储数据的“容器”,简单理解是一个个的盒子。

  2. 变量有什么作用呢? 用来存放数据的。注意变量指的是容器而不是数据。

  3. 你还能想到那些生活中的变量?

    HTML标签

    教室

    宿舍

变量在内存中的存储

本质:变量是程序在内存中申请的一块用来存放数据的空间

类似我们酒店的房间,一个房间就可以看做是一个变量。

image.png

2. 变量的使用

变量在使用时分为两步: 1. 声明变量 2. 赋值

1. 声明变量

要想使用变量,首先需要创建变量(也称为声明变量或者定义变量)

语法:

let 变量名

声明变量有两部分构成:声明关键字、变量名(标识)

let 即关键字 (let: 允许、许可、让、要),所谓关键字是系统提供的专门用来声明(定义)变量的词语

//举例:
let age
我们声明了一个age变量
age 即变量的名称,也叫标识符
  • (了解,目前几乎不用 var )
  • 也可以使用 var age; 声明一个age变量
  • var 是一个 JS关键字,用来声明变量( variable 变量的意思 )。使用该关键字声明变量后,计算机会自动为变量分配内存空间,不需要程序员管
  • age 是程序员定义的变量名,我们要通过变量名来访问内存中分配的空间 image.png

2. 变量赋值

定义了一个变量后,你就能够初始化它(赋值)。在变量名之后跟上一个“=”,然后是数值。

image.png

注意:是通过变量名来获得变量里面的数据

age = 10 // 给 age 这个变量赋值为 10
  • = 用来把右边的值赋给左边的变量空间中 此处代表赋值的意思
  • 变量值是程序员保存到变量空间里的值

3. 变量初始化

声明变量的时候直接完成赋值操作,这种操作也称为 变量初始化

// 声明了一个age变量,同时里面存放变量了 18 这个数字
let age = 18;

前三小节小结

  1. 变量用什么关键字来声明?

    let

  2. 变量通过什么符号来赋值?

    = 这个符号我们也称为 赋值运算符

  3. 开发中我们经常声明的同时可以直接赋值?

    let age = 18

4. 更新变量

变量赋值后,还可以通过简单地给它一个不同的值来更新它。

let age = 18
age = 81 // 最后的结果就是81因为18 被覆盖掉了

注意: let 不允许多次声明一个变量。会报错。

let age = 18
let age = 81

image.png

5.同时声明多个变量

同时声明多个变量时,只需要写一个 let,多个变量名中间用英文逗号隔开。

let age = 10, name = 'zs', sex = 2

注意:看上去代码长度更短,但并不推荐这样。为了更好的可读性,请一行只声明一个变量

四五小节总结

  1. 变量赋值之后如何更新新值?

    直接给它一个不同的值来更新它

  2. 我们提倡同时声明多个不同的变量吗?

    不提倡, 可读性不好

    //多行变量声明有点长,但更容易阅读
    let age = 18
    let uname = 'pink'
    

3. 变量的本质

内存:计算机中存储数据的地方,相当于一个空间

变量本质:是程序在内存中申请的一块用来存放数据的小空间

image.png

4. 变量命名规则与规范

规则:必须遵守,不遵守报错 (法律层面)

规范:建议,不遵守不会报错,但不符合业内通识 (道德层面)

  1. 规则:

    • 不能用关键字

      关键字:有特殊含义的字符,JavaScript 内置的一些英语词汇。例如:let、var、if、for等

      (不能 是关键字、保留字。例如:var、for、while)

    • 只能用下划线、字母、数字、$ 组成,且数字不能开头

      字母(A-Za-z)、数字(0-9)、下划线(_)、美元符号( $ )组成

    • 字母严格区分大小写,如 Age 和 age 是不同的变量

  2. 规范:

    • 起名要有意义

    • 遵守小驼峰命名法

      第一个单词首字母小写,后面每个单词首字母大写。例:userName

5. 变量拓展-let和var的区别

let 和 var 区别:

在较旧的JavaScript,使用关键字 var 来声明变量 ,而不是 let。

var 现在开发中一般不再使用它,只是我们可能再老版程序中看到它。

let 为了解决 var 的一些问题。

var 声明:

  • 可以先使用 在声明 (不合理)
  • var 声明过的变量可以重复声明(不合理)
  • 比如变量提升、全局变量、没有块级作用域等等

结论:

var 就是个bug,别迷恋它了,以后声明变量我们统一使用 let

6. 变量声明 let var const

  • 变量声明有三个 var let 和 const
  • 我们应该用那个呢?
  • 首先var 先排除,老派写法,问题很多,可以淘汰掉…
  • let or const ?
  • 建议: const 优先,尽量使用const,原因是:
    • const 语义化更好
    • 很多变量我们声明的时候就知道他不会被更改了,那为什么不用 const呢?
    • 实际开发中也是,比如react框架,基本const
  • 如果你还在纠结,那么我建议:
    • 有了变量先给const,如果发现它后面是要被修改的,再改为let

关于const

  • const 声明的值不能更改,而且const声明变量的时候需要里面进行初始化
  • 但是对于引用数据类型,const声明的变量,里面存的不是 值,不是值,不是值,是 地址。
  • const声明的对象可以修改里面的属性,因为对象是引用类型,里面存储的是地址,只要地址不变,就不会报错 image.png

image.png

小结

为什么需要变量?

  • 因为我们一些数据需要保存,所以需要变量

变量是什么?

变量就是一个容器,用来存放数据的。方便我们以后使用里面的数据

变量的本质是什么?

变量是内存里的一块空间,用来存储数据。

变量怎么使用的?

  • 我们使用变量的时候,一定要声明变量,然后赋值
  • 声明变量本质是去内存申请空间。

什么是变量的初始化?

声明变量并赋值我们称之为变量的初始化

3. 常量

常量的使用

概念:使用 const 声明的变量称为“常量”。

使用场景:当某个变量永远不会改变的时候,就可以使用 const 来声明,而不是let。

命名规范:和变量一致

常量使用:const PI = 3.14

注意: 常量不允许重新赋值,声明的时候必须赋值(初始化)

小技巧:不需要重新赋值的数据使用const

let、var、const

let — 现在实际开发变量声明方式。

var — 以前的声明变量的方式,会有很多问题。

const — 类似于 let ,但是变量的值无法被修改。

4. 数据类型

数据类型简介

为什么需要数据类型

计算机世界中的万事万物都是数据。

计算机程序可以处理大量的数据,为什么要给数据分类?

    1. 更加充分和高效的利用内存
    1. 也更加方便程序员的使用数据

在计算机中,不同的数据所需占用的存储空间是不同的,为了便于把数据分成所需内存大小不同的数据,充分利用存储空间,于是定义了不同的数据类型。

简单来说,数据类型就是数据的类别型号。比如姓名“张三”,年龄18,这些数据的类型是不一样的。

变量的数据类型

变量是用来存储值的所在处,它们有名字和数据类型。变量的数据类型决定了如何将代表这些值的位存储到计算机的内存中。JavaScript 是一种弱类型或者说动态语言。这意味着不用提前声明变量的类型,在程序运行过程中,类型会被自动确定。

var age = 10; // 这是一个数字型
var areYouOk = '是的'; // 这是一个字符串

在代码运行时,变量的数据类型是由 JS引擎 根据 = 右边变量值的数据类型来判断 的,运行完毕之后, 变量就确定了数据类型。

JavaScript 拥有动态类型,同时也意味着相同的变量可用作不同的类型:

var x = 6; // x 为数字
var x = "Bill"; // x 为字符串

数据类型的分类

JS 数据类型整体分为两大类:

  • 基本数据类型(简单数据类型)
  • 引用数据类型(复杂数据类型)

基本数据类型:number 数字型、string 字符串型、boolean 布尔型、undefined 未定义型、null 空类型

引用数据类型:object 对象

简单数据类型

简单数据类型(基本数据类型)

JavaScript 中的简单数据类型及其说明如下:

image.png

数字型 Number

我们数学中学习到的数字,可以是整数、小数、正数、负数。

JavaScript 中的正数、负数、小数等 统一称为 数字类型。

注意事项

JS 是弱数据类型,变量到底属于那种类型,只有赋值之后,我们才能确认

Java是强数据类型 例如 int a = 3 必须是整数

let age = 21 // 整数
let Age = 21.3747 // 小数
数字的操作(算术运算符)

数字可以有很多操作,比如,乘法 * 、除法 / 、加法 + 、减法 - 等等,所以经常和算术运算符一起。

数学运算符也叫算术运算符,主要包括加、减、乘、除、取余(求模)。

  • +:求和

  • -:求差

  • *:求积

  • /:求商

  • %:取模(取余数)

    开发中经常作为某个数字是否被整除

算术运算符执行的优先级顺序

同时使用多个运算符编写程序时,会按着某种顺序先后执行,我们称为优先级。

JavaScript中 优先级越高越先被执行,优先级相同时以书从左向右执行。

  • 乘、除、取余优先级相同
  • 加、减优先级相同
  • 乘、除、取余优先级大于加、减
  • 使用 () 可以提升优先级
  • 总结: 先乘除后加减,有括号先算括号里面的~~~
NaN

NaN(Not a number) 代表一个计算错误。它是一个不正确的或者一个未定义的数学操作所得到的结果

NaN 是粘性的。任何对 NaN 的操作都会返回 NaN

console.log('pink老师' - 2) // NaN
console.log(NaN - 2) // NaN
console.log(NaN === NaN) // false
数字型进制

最常见的进制有二进制、八进制、十进制、十六进制。

// 1.八进制数字序列范围:0~7
var num1 = 07; // 对应十进制的7
var num2 = 019; // 对应十进制的19
var num3 = 08; // 对应十进制的8
// 2.十六进制数字序列范围:0~9以及A~F
var num = 0xA;

现阶段我们只需要记住,在JS中八进制前面加0,十六进制前面加 0x

数字型范围

JavaScript中数值的最大和最小值

alert(Number.MAX_VALUE); // 1.7976931348623157e+308
alert(Number.MIN_VALUE); // 5e-324
  • 最大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308
  • 最小值:Number.MIN_VALUE,这个值为:5e-32
数字型三个特殊值
  • Infinity ,代表无穷大,大于任何数值
  • -Infinity ,代表无穷小,小于任何数值
  • NaN ,Not a number,代表一个非数值
isNaN()

用来判断一个变量是否为非数字的类型,返回 true(不是数字) 或者 false(数字)

var usrAge = 21;
var isOk = isNaN(userAge);
console.log(isNum); // false ,21 不是一个非数字
var usrName = "andy";
console.log(isNaN(userName)); // true ,"andy"是一个非数字

字符串型 String

字符串概念和嵌套

通过单引号('')、双引号("")或反引号( ` ) 包裹的数据都叫字符串,单引号和双引号没有本质上的区别,推荐使用单引号

注意事项:

  1. 无论单引号或是双引号必须成对使用
  2. 单引号/双引号可以互相嵌套,但是不以自已嵌套自已(口诀:外双内单,或者外单内双)
  3. 必要时可以使用转义符 \,输出单引号或双引号
字符串拼接

场景: + 运算符 可以实现字符串的拼接。

口诀:数字相加,字符相连

  • 多个字符串之间可以使用 + 进行拼接,其拼接方式为 字符串 + 任何类型 = 拼接之后的新字符串
  • 拼接前会把与字符串相加的任何类型转成字符串,再拼接成一个新的字符串
  • 因为 HTML 标签里面的属性使用的是双引号,JS 这里我们更推荐使用单引号
//1.1 字符串 "相加"
alert('hello' + ' ' + 'world') // hello world
//1.2 数值字符串 "相加"
alert('100' + '100') // 100100
//1.3 数值字符串 + 数值
alert('11' + 12) // 1112

let age = 18
// console.log('pink老师age岁啦') // 这样不行哦
console.log('pink老师' + age + '岁啦') // pink老师18岁啦

let strMsg = "我爱北京天安门~" // 使用双引号表示字符串
let strMsg2 = '我爱吃猪蹄~' // 使用单引号表示字符串
// 常见错误
let strMsg3 = 我爱大肘子 // 报错,没使用引号,会被认为是js代码,但js没有这些语法

注意:

  • 我们经常会将字符串和变量来拼接,因为变量可以很方便地修改里面的值
  • 变量是不能添加引号的,因为加引号的变量会变成字符串
  • 如果变量两侧都有字符串拼接,口诀“引引加加 ”,删掉数字,变量写加中间
模板字符串
  • 使用场景
    • 拼接字符串和变量
    • 没有它之前,要拼接变量比较麻烦
  • 语法
    • `` (反引号)
    • 在英文输入模式下按键盘的tab键上方那个键(1左边那个键)
    • 内容拼接变量时,用 ${ } 包住变量
//普通单引号字符串
document.write('大家好,我叫' + uname + ', 我今年贵庚' + age + '岁了')
//模板字符串
document.write(`大家好,我叫${uname}, 我今年贵庚${age}岁了`)
前三小节总结
  1. JavaScript中什么样数据我们知道是字符串类型?

    只要用 单引号、双引号、反引号包含起来的就是字符串类型

  2. 字符串拼接比较麻烦,我们可以使用什么来解决这个问题?

    模板字符串, 可以让我们拼接字符串更简便

  3. 模板字符串使用注意事项:

    用什么符号包含数据? 反引号

    用什么来使用变量? ${变量名}

字符串转义符

类似HTML里面的特殊字符,字符串中也有特殊字符,我们称之为转义符。

转义符都是 \ 开头的,常用的转义符及其说明如下:

image.png

字符串长度

字符串是由若干字符组成的,这些字符的数量就是字符串的长度。通过字符串的 length 属性可以获取整个字符串的长度

var strMsg = "我是帅气多金的程序猿!";
alert(strMsg.length); // 显示 11

布尔型 Boolean

表示肯定或否定时在计算机中对应的是布尔类型数据。

它有两个固定的值 true 和 false,表示肯定的数据用 true(真),表示否定的数据用 false(假)。

布尔型和数字型相加的时候, true 的值为 1 ,false 的值为 0。

console.log(true + 1); // 2
console.log(false + 1); // 1

未定义类型 Undefined

未定义是比较特殊的类型,只有一个值 undefined。

什么情况出现未定义类型?

只声明变量,不赋值的情况下,变量的默认值为 undefined,一般很少【直接】为某个变量赋值为 undefined。

工作中的使用场景:

我们开发中经常声明一个变量,等待传送过来的数据。

如果我们不知道这个数据是否传递过来,此时我们可以通过检测这个变量是不是undefined,就判断用户是否有数据传递过来

注意:如果进行相连或者相加时,注意结果

let age 声明变量但未赋值
document.write(age)  //输出 undefined

console.log('你好' + age) // 你好undefined
console.log(11 + age) // NaN
console.log(true + age) // NaN

空类型 Null

JavaScript 中的 null 仅仅是一个代表“无”、“空”或“值未知”的特殊值

let obj = null 
console.log(obj)  //输出 null

console.log('你好' + obj) // 你好null
console.log(11 + obj) // 11
console.log(true + obj) // 1

null 和 undefined 区别:

  • undefined 表示没有赋值
  • null 表示赋值了,但是内容为空

null 开发中的使用场景

官方解释:把 null 作为尚未创建的对象

大白话: 将来有个变量里面存放的是一个对象,但是对象还没创建好,可以先给个null

检测数据类型

控制台输出语句和检测数据类型

  • 控制台语句经常用于测试结果来使用。
  • 可以看出数字型和布尔型颜色为蓝色,字符串和undefined颜色为灰色

image.png

通过 typeof 关键字检测数据类型

typeof 运算符可以返回被检测的数据类型,它支持两种语法形式:

  1. 作为运算符: typeof x (常用的写法)

  2. 函数形式: typeof(x)

换言之,有括号和没有括号,得到的结果是一样的,所以我们直接使用运算符的写法。

var num = 18;
console.log(typeof num) // 结果 number

不同类型的返回值

image.png

数据类型转换

什么是数据类型转换,为什么需要数据类型转换

JavaScript是弱数据类型: JavaScript也不知道变量到底属于哪种数据类型,只有赋值了才清楚。

坑:使用表单、prompt 获取过来的数据默认是字符串类型的,此时就不能直接简单的进行加法运算,此时需要转换变量的数据类型。

通俗来说,就是把一种数据类型的变量转换成我们需要的数据类型

隐式转换

某些运算符被执行时,系统内部自动将数据类型进行转换,这种转换称为隐式转换。

  • 规则:

    • + 号两边只要有一个是字符串,都会把另外一个转成字符串
    • 除了+以外的算术运算符 比如 - * / 等都会把数据转成数字类型
  • 缺点:

    转换类型不明确,靠经验才能总结

  • 小技巧:

    • +号作为正号解析可以转换成数字型

      console.log(+'123')结果为数字123

      console.log(+'123' + 123)结果为数字246

    • 任何数据和字符串相加结果都是字符串

image.png

显式转换

编写程序时过度依靠系统内部的隐式转换是不严禁的,因为隐式转换规律并不清晰,大多是靠经验总结的规律。

为了避免因隐式转换带来的问题,通常根逻辑需要对数据进行显示转换。

  • 概念:

    自己写代码告诉系统该转成什么类型

  • 转换为数字型

    • Number(数据)

      • 转成数字类型
      • 如果字符串内容里有非数字,转换失败时结果为 NaN(Not a Number)即不是一个数字
      • NaN也是number类型的数据,代表非数字
    • parseInt(数据)

      只保留整数

    • parseFloat(数据)

      可以保留小数

  • 转换为字符型:

    • String(数据)
    • 变量.toString(进制)

显示转换具体信息如下:

我们通常会实现3种方式的转换:

  • 转换为字符串类型
  • 转换为数字型
  • 转换为布尔型

转换为字符串

image.png

  • toString() 和 String() 使用方式不一样。
  • 三种转换方式,我们更喜欢用第三种加号拼接字符串转换方式, 这一种方式也称之为隐式转换。

转换为数字型(重点)

image.png

  • 注意 parseInt 和 parseFloat 单词的大小写,这2个是重点
  • 隐式转换是我们在进行算数运算的时候,JS 自动转换了数据类型
console.log(parseInt('3.94')) // 结果 3
console.log(parseInt('120px')) // 结果 120
console.log(parseInt('rem120px')) // 结果 NaN
console.log(parseFloat('3.94')) // 结果 3.94
console.log(parseFloat('120px')) // 结果 120
console.log(parseFloat('rem120px')) // 结果 NaN
console.log(Number('12.34')) // 结果12.34
console.log(Number('120px')) // 结果NaN

转换为布尔型

image.png

  • 代表空、否定的值会被转换为 false ,如 ''、0、NaN、null、undefined、false

  • 其余值都会被转换为 true

  • 隐式转换:

    1. 有字符串的加法 “” + 1 ,结果是 “1”

    2. 减法 - (像大多数数学运算一样)只能用于数字,它会使空字符串 "" 转换为 0

    3. null 经过数字转换之后会变为 0

    4. undefined 经过数字转换之后会变为 NaN

console.log(Boolean('')); // false
console.log(Boolean(0)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean('小白')); // true
console.log(Boolean(12)); // true

5. JavaScript 运算符

image.png

运算符

运算符(operator)也被称为操作符,是用于实现赋值、比较和执行算数运算等功能的符号。

JavaScript中常用的运算符有:

  • 算数运算符
  • 赋值运算符
  • 一元运算符(递增和递减运算符)
  • 比较运算符
  • 逻辑运算符

算数运算符(前面数字类型的操作已经了解过)

概述

概念:算术运算使用的符号,用于执行两个变量或值的算术运算。

image.png

浮点数的精度问题

浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数。

var result = 0.1 + 0.2; // 结果不是 0.3,而是:0.30000000000000004
console.log(0.07 * 100); // 结果不是 7, 而是:7.000000000000001

所以:不要直接判断两个浮点数是否相等 !

注意:算术运算符优先级:先乘除,后加减,有小括号先算小括号里面的

表达式和返回值

表达式:是由数字、运算符、变量等以能求得数值的有意义排列方法所得的组合

简单理解:是由数字、运算符、变量等组成的式子

表达式最终都会有一个结果,返回给我们,我们成为返回值

赋值运算符

概念:对变量进行赋值的运算符(用来把数据赋值给变量的运算符)。

  • 已经学过的赋值运算符:= 将等号右边的值赋予给左边, 要求左边必须是一个容器

  • 其他赋值运算符:

image.png

使用这些运算符可以在对变量赋值时进行快速操作,比如+= 出现是为了简化代码

let age = 10
age += 5 // 相当于 age = age + 5;
age -= 5 // 相当于 age = age - 5;
age *= 10 // 相当于 age = age * 10;

一元运算符

众多的 JavaScript 的运算符可以根据所需表达式的个数,分为一元运算符、二元运算符、三元运算符

一元: 仅操作一个操作数。

  • 二元运算符: eg.let num = 10 + 20

  • 一元运算符:eg.正负号 +123 -'123'

    问题: 我们以前让一个变量每次+1 ,以前我们做的呢?

    let num = 10

    num = num + 1 //方式一

    num += 1 //方式二

  • 我们可以有更简便的写法了

    • 自增:

      符号:++

      作用:让变量的值 +1

    • 自减:

      符号:--

      作用:让变量的值 -1

    使用场景:经常用于计数来使用。 比如进行10次操作,用它来计算进行了多少次了

    自增运算符的用法:

image.png

image.png

注意

  1. 前置自增和后置自增独立使用时二者并没有差别
  2. 一般开发中我们都是独立使用
  3. 后面 i++ 后置自增会使用相对较多,并且都是单独使用

下面是详细说明

递增和递减运算符概述

如果需要反复给数字变量添加或减去1,可以使用递增(++)和递减(--)运算符来完成。

在 JavaScript 中,递增(++)和递减(-- )既可以放在变量前面,也可以放在变量后面。放在变量前面时,我们可以称为前置递增(递减)运算符,放在变量后面时,我们可以称为后置递增(递减)运算符。

注意:递增和递减运算符必须和变量配合使用。

递增运算符

前置递增运算符

++num 前置递增,就是自加1,类似于 num = num + 1,但是 ++num 写起来更简单。

使用口诀:先自加,后返回值

var num = 10;
alert(++num + 10); // 21
后置递增运算符

num++ 后置递增,就是自加1,类似于 num = num + 1 ,但是 num++ 写起来更简单。

使用口诀:先返回原值,后自加

var num = 10;
alert(10 + num++); // 20
小结
  • 前置递增和后置递增运算符可以简化代码的编写,让变量的值 + 1 比以前写法更简单
  • 单独使用时,运行结果相同
  • 与其他代码联用时,执行结果会不同
  • 后置:先原值运算,后自加(先人后己)
  • 前置:先自加,后运算(先已后人)
  • 开发时,大多使用后置递增/减,并且代码独占一行,例如:num++; 或者 num--;

比较运算符(关系运算符)

比较运算符的介绍

使用场景:比较两个数据大小、是否相等

概念:比较运算符(关系运算符)是两个数据进行比较时所使用的运算符,比较运算后,会返回一个布尔值(true / false)作为比较运算的结果

image.png

=对比小结

image.png 开发中判断是否相等,强烈推荐使用 ===

比较运算符的细节

  • 字符串比较,是比较的字符对应的ASCII码

    • 从左往右依次比较
    • 如果第一位一样再比较第二位,以此类推
    • 比较的少,了解即可
  • NaN不等于任何值,包括它本身

    涉及到"NaN“都是false

  • 尽量不要比较小数,因为小数有精度问题

  • 不同类型之间比较会发生隐式转换

    • 最终把数据隐式转换转成number类型再比较
    • 所以开发中,如果进行准确的比较我们更喜欢 === 或者 !==

逻辑运算符

概述

  • 提问:如果我想判断一个变量 num 是否大于5且小于10,怎么办?

    错误写法: 5 < num < 10

  • 使用场景:逻辑运算符用来解决多重条件判断

    正确写法: num > 5 && num < 10

概念:逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值。后面开发中经常用于多个条件的判断

image.png

逻辑与&&

两边都是 true才返回 true,否则返回 false

image.png

逻辑或 ||

两边都为 false 才返回 false,否则都为true

image.png

逻辑非 !

逻辑非(!)也叫作取反符,用来取一个布尔值相反的值,如 true 的相反值是 false

var isOk = !true;
console.log(isOk); // false

短路运算(逻辑中断)

短路:只存在于 && 和 || 中,当满足一定条件会让右边代码不执行

短路运算的原理:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值;

image.png

  • 原因:通过左边能得到整个式子的结果,因此没必要再判断右边
  • 运算结果:无论 && 还是 || ,运算结果都是最后被执行的表达式值,一般用在变量赋值
逻辑与
  • 语法: 表达式1 && 表达式2
  • 如果第一个表达式的值为真,则返回表达式2
  • 如果第一个表达式的值为假,则返回表达式1
console.log( 123 && 456 ); // 456
console.log( 0 && 456 ); // 0
console.log( 123 && 456&& 789 ); // 789
逻辑或
  • 语法: 表达式1 || 表达式2
  • 如果第一个表达式的值为真,则返回表达式1
  • 如果第一个表达式的值为假,则返回表达式2
console.log( 123 || 456 ); // 123
console.log( 0 || 456 ); // 456
console.log( 123 || 456 || 789 ); // 123

var num = 0;
console.log(123 || num++);
console.log(num);//0,因为中断了,后面没有执行

运算符优先级

image.png

  • 一元运算符里面的逻辑非优先级很高
  • 逻辑与比逻辑或优先级高

6. JavaScript 流程控制语句

表达式和语句

  • 表达式:

    表达式是可以被求值的代码,JavaScript 引擎会将其计算出一个结果。

    x = 7

    num++

  • 语句:

    语句是一段可以执行的代码。

    比如: prompt() 可以弹出一个输入框,还有 if语句 for 循环语句等等

  • 表达式和语句的区别

    • 表达式:因为表达式可被求值,所以它可以写在赋值语句的右侧。

      表达式 num = 3 + 4

    • 语句:而语句不一定有值,所以比如 alert() for和break 等语句就不能被用于赋值。

      语句 alert() 弹出对话框 console.log() 控制台打印输出

某些情况,也可以把表达式理解为表达式语句,因为它是在计算结果,但不是必须的成分 (例如continue语句)

流程控制

在一个程序执行的过程中,各条代码的执行顺序对程序的结果是有直接影响的。很多时候我们要通过控制代码的执行顺序来实现我们要完成的功能。

简单理解: 流程控制就是来控制我们的代码按照什么结构顺序来执行

程序三大流程控制语句

流程控制主要有三种结构,分别是顺序结构分支结构循环结构,这三种结构代表三种代码执行的顺序。

  • 以前我们写的代码,写几句就从上往下执行几句,这种叫顺序结构
  • 有的时候要根据条件选择执行代码,这种就叫分支结构
  • 某段代码被重复执行,就叫循环结构

image.png

顺序流程控制语句

顺序结构是程序中最简单、最基本的流程控制,它没有特定的语法结构,程序会按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。

image.png

分支流程控制语句

分支语句可以让我们有选择性的执行想要的代码

分支语句包含:

  • If分支语句
  • 三元运算符
  • switch 语句
分支结构

由上到下执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程),从而得到不同的结果

image.png

语句可以理解为一个行为,循环语句和分支语句就是典型的语句。一个程序由很多个语句组成,一般情况下,会分割成一个一个的语句。

分支流程控制 if 语句
  • if语句有三种使用:单分支、双分支、多分支
单分支 if 语法

语法结构

// 条件成立执行代码,否则什么也不做
if (条件表达式) {
    // 条件成立执行的代码语句
}
  • 括号内的条件为true时,进入大括号里执行代码
  • 小括号内的结果若不是布尔类型时,会发生隐式转换转为布尔类型
  • 如果大括号只有一个语句,大括号可以省略,但是,俺们不提倡这么做~

执行流程

image.png

双分支if语法(if else)

语法结构

// 条件成立 执行 if 里面代码,否则执行else 里面的代码
if (条件表达式) {
    // [如果] 条件成立执行的代码
} else {
    // [否则] 不满足条件执行的代码
}

执行流程

image.png

多分支if语法(if else if 语句)

使用场景:适合于有多个结果的时候,比如学习成绩可以分为:优 良 中 差

就是利用多个条件来选择不同的语句执行,得到不同的结果,多选1的过程

语法结构

// 适合于检查多重条件。
if (条件表达式1) {
    语句1;
} else if (条件表达式2) {
    语句2;
} else if (条件表达式3) {
    语句3;
    ....
} else {
    // 上述条件都不成立执行此处代码
}

释义:

  • 先判断条件1,若满足条件1就执行代码1,其他不执行
  • 若不满足则向下判断条件2,满足条件2执行代码2,其他不执行
  • 若依然不满足继续往下判断,依次类推
  • 若以上条件都不满足,执行else里的代码n
  • 注:可以写N个条件,但这里演示只写2个

执行流程

image.png

三元表达式(三元运算符)
  • 使用场景: 其实是比 if 双分支 更简单的写法,可以使用 三元表达式
  • 符号:? 与 : 配合使用
  • 语法:条件 ? 满足条件执行的代码 : 不满足条件执行的代码
  • 一般用来取值
  • 简单理解:就类似于 if else (双分支) 的简写

三元表达式也能做一些简单的条件选择。 有三元运算符组成的式子称为三元表达式

分支流程控制 switch 语句

语法结构

switch 语句也是多分支语句,它用于基于不同的条件来执行不同的代码。当要针对变量设置一系列的特定值的选项时,就可以使用 switch。

switch( 表达式 ){
    case value1:
        // 表达式 等于 value1 时要执行的代码
        break;
    case value2:
        // 表达式 等于 value2 时要执行的代码
        break;
    default:
        // 表达式 不等于任何一个 value 时要执行的代码
}
  • 找到跟小括号里数据全等的case值,并执行里面对应的代码
  • 若没有全等 === 的则执行default里的代码
  • switch :开关 转换 , case :小例子 选项
  • 关键字 switch 后面括号内可以是表达式或值, 通常是一个变量
  • 关键字 case , 后跟一个选项的表达式或值,后面跟一个冒号
  • switch 表达式的值会与结构中的 case 的值做比较
  • 如果存在匹配全等(===) ,则与该 case 关联的代码块会被执行,并在遇到 break 时停止,整个 switch 语句代码执行结束
  • 如果所有的 case 的值都和表达式的值不匹配,则执行 default 里的代码

注意事项

  1. switch case语句一般用于等值判断,不适合于区间判断
  2. switch case一般需要配合break关键字使用 没有break会造成case穿透(继续执行下一个case里面的语句)
switch 语句和 if else if 语句的区别

一般情况下,它们两个语句可以相互替换

  • switch...case 语句通常处理 case为比较确定值的情况, 而 if…else…语句更加灵活,常用于范围判断(大于、等于某个范围)
  • switch 语句进行条件判断后直接执行到程序的条件语句,效率更高。而if…else 语句有几种条件,就得判断多少次。
  • 当分支比较少时,if… else语句的执行效率比 switch语句高。
  • 当分支比较多时,switch语句的执行效率比较高,而且结构更清晰。

循环流程控制语句

断点调试
  • 作用:学习时可以帮助更好的理解代码运行,工作时可以更快找到bug

  • 浏览器打开调试界面

    浏览器中按 F12 打开开发者工具--> 点到sources一栏 -->找到需要调试的文件-->在程序的某一行设置断点(打了断点后一定要刷新页面)

  • 断点:在某句代码上加的标记就叫断点,当程序执行到这句有标记的代码时会暂停下来

断点调试是指自己在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后你可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。

断点调试可以帮我们观察程序的运行过程

Watch: 监视,通过watch可以监视变量的值的变化,非常的常用。

F11: 程序单步执行,让程序一行一行的执行,这个时候,观察watch中变量的值的变化。

循环

循环目的:在实际问题中,有许多具有规律性的重复操作,因此在程序中要完成这类操作就需要重复执行某些语句(简单说:可以重复执行某些代码,通常跟计数有关)

在Js 中,主要有三种类型的循环语句:

  • for 循环
  • while 循环
  • do...while 循环
for 循环语法
  • 作用:重复执行代码
  • 好处:把声明起始值、循环条件、变化值写到一起,让人一目了然,它是最常使用的循环形式

在程序中,一组被重复执行的语句被称之为循环体,能否继续重复执行,取决于循环的终止条件。由循环体及循环的终止条件组成的语句,被称之为循环语句

语法结构

for 循环主要用于把某些代码循环若干次,通常跟计数有关系。其语法结构如下:

for(变量起始值; 终止条件; 变量变化值 ){
    //循环体
}
  • 初始化变量:通常被用于初始化一个计数器,该表达式可以使用 var 关键字声明新的变量,这个变量帮我们来记录次数。
  • 条件表达式:用于确定每一次循环是否能被执行,就是终止条件。如果结果是 true 就继续循环,否则退出循环。
  • 操作表达式:每次循环的最后都要执行的表达式。通常被用于更新或者递增计数器变量。当然,递减变量也是可以的。
执行过程
  1. 初始化变量,初始化操作在整个 for 循环只会执行一次。

  2. 执行条件表达式,如果为true,则执行循环体语句,否则退出循环,循环结束。

  3. 执行操作表达式,此时第一轮结束。

  4. 第二轮开始,直接去执行条件表达式(不再初始化变量),如果为 true ,则去执行循环体语句,否则退出循环。

  5. 继续执行操作表达式,第二轮结束。

  6. 后续跟第二轮一致,直至条件表达式为假,结束整个 for 循环。

//for 循环重复相同的代码

// 基本写法
for(var i = 1; i <= 10; i++){
    console.log('媳妇我错了~');
}
// 用户输入次数
var num = prompt('请输入次数:');
for ( var i = 1 ; i <= num; i++) {
    console.log('媳妇我错了~');
}
//for 循环重复不相同的代码
//for 循环还可以重复不同的代码,这主要是因为使用了计数器 ,计数器在每次循环过程中都会有变化。

// 基本写法
for (var i = 1; i <= 100; i++) {
    console.log('这个人今年' + i + '岁了');
}
循环嵌套(双重 for 循环)

很多情况下,单层 for 循环并不能满足我们的需求,比如我们要打印一个 5 行 5 列的图形、打印一个倒直角三角形等,此时就可以通过循环嵌套来实现。 注意:外层循环控制行数,内层循环控制列数

image.png 循环嵌套是指在一个循环语句中再定义一个循环语句的语法结构,例如在for循环语句中,可以再嵌套一个for 循环,这样的 for 循环语句我们称之为双重for循环。

for (外循环的初始(记录循环次数的变量); 外循环的循环条件; 外循环的变化值) {
    for (内循环的初始; 内循环的循环条件; 内循环的变化值) {
        循环体
    }
}
  • 内层循环可以看做外层循环的语句
  • 内层循环执行的顺序也要遵循 for 循环的执行顺序
  • 外层循环执行一次,内层循环要执行全部次数
小结
  • for 循环可以重复执行某些相同代码
  • for 循环可以重复执行些许不同的代码,因为我们有计数器
  • for 循环可以重复执行某些操作,比如算术运算符加法操作
  • 随着需求增加,双重for循环可以做更多、更好看的效果
  • 双重 for 循环,外层循环一次,内层 for 循环全部执行
  • for 循环是循环条件和数字直接相关的循环
  • 分析要比写代码更重要
  • 一些核心算法想不到,但是要学会,分析它执行过程
  • 举一反三,自己经常总结,做一些相似的案例
while 循环

循环:重复执行一些操作, while : 在…. 期间, 所以 while循环 就是在满足条件期间,重复执行某些代码。

比如我们运行相同的代码输出5次(输出5句 “我学的很棒”)

while 语句可以在条件表达式为真的前提下,循环执行指定的一段代码,直到表达式不为真时结束循环。

while语句的语法结构如下:

while (循环条件) {
    要重复执行的代码(循环体)
}

释义:

  • 跟if语句很像,都要满足小括号里的条件为true才会进入 循环体 执行代码
  • while大括号里代码执行完毕后不会跳出,而是继续回到小括号里判断条件是否满足,若满足又执行大括号里的代码,然后再回到小括号判断条件,直到括号内条件不满足,即跳出

while 循环三要素:

循环的本质就是以某个变量为起始值,然后不断产生变化量,慢慢靠近终止条件的过程。

所以,while循环需要具备三要素:

  1. 变量起始值

  2. 终止条件(没有终止条件,循环会一直执行,造成死循环)

  3. 变量变化量(用自增或者自减)

注意

  • 使用 while 循环时一定要注意,它必须要有退出条件,否则会成为死循环
  • while 循环和 for 循环的不同之处在于 while 循环可以做较为复杂的条件判断,比如判断用户名和密码
do while 循环(了解)

do... while 语句其实是 while 语句的一个变体。该循环会先执行一次代码块,然后对条件表达式进行判断,如果条件为真,就会重复执行循环体,否则退出循环。

do... while 语句的语法结构如下:

do {
    // 循环体代码 - 条件表达式为 true 时重复执行循环体代码
} while(条件表达式);

执行思路:

  1. 先执行一次循环体代码
  2. 再执行条件表达式,如果结果为 true,则继续执行循环体代码,如果为 false,则退出循环,继续执行后面代码

注意:先再执行循环体,再判断,我们会发现 do…while 循环语句至少会执行一次循环体代码

循环小结
  • 当如果明确了循环的次数的时候推荐使用for循环
  • 当不明确循环的次数的时候推荐使用while循环
  • JS 中循环有 for 、while 、 do while
  • 三个循环很多情况下都可以相互替代使用
  • 如果是用来计次数,跟数字相关的,三者使用基本相同,但是我们更喜欢用 for
  • while 和 do…while 可以做更复杂的判断条件,比 for 循环灵活一些
  • while 和 do…while 执行顺序不一样,while 先判断后执行,do…while 先执行一次,再判断执行
  • while 和 do…while 执行次数不一样,do…while 至少会执行一次循环体, 而 while 可能一次也不执行
  • 实际工作中,我们更常用for 循环语句,它写法更简洁直观, 所以这个要重点学习
循环退出 continue break
  • 循环结束:

    break:退出循环

    continue:结束本次循环,继续下次循环

  • 区别:

    • continue 退出本次循环,一般用于排除或者跳过某一个选项的时候, 可以使用continue
    • break 退出整个循环,一般用于结果已经得到, 后续的循环不需要的时候可以使用
continue 关键字

continue 关键字用于立即跳出本次循环,继续下一次循环(本次循环体中 continue 之后的代码就会少执行一次)。

例如,吃5个包子,第3个有虫子,就扔掉第3个,继续吃第4个第5个包子,其代码实现如下

for (var i = 1; i <= 5; i++) {
    if (i == 3) {
        console.log('这个包子有虫子,扔掉');
        continue; // 跳出本次循环,直接跳到i++,跳出的是第3次循环
    }
    console.log('我正在吃第' + i + '个包子呢');
}
break 关键字

break 关键字用于立即跳出整个循环(循环结束)。

例如,吃5个包子,吃到第3个发现里面有半个虫子,其余的不吃了,其代码实现如下:

for (var i = 1; i <= 5; i++) {
    if (i == 3) {
        break; // 直接退出整个for 循环,跳到整个for下面的语句
    }
    console.log('我正在吃第' + i + '个包子呢');
}

7. JavaScript数组

数组 (Array) —— 一种将 一组数据存储在单个变量名下 的优雅方式

image.png

数组的最新使用

  1. 声明语法

    let 数组名 = [数据1, 数据2, ..., 数据n]

    eg. let names = ['小红', '小明']

    • 数组是按顺序保存,所以每个数据都有自己的编号
    • 计算机中的编号从0开始,所以小明的编号为0,小刚编号为1,以此类推
    • 在数组中,数据的编号也叫索引或下标
    • 数组可以存储任意类型的数据
  2. 取值语法

    数组名[下标]

    • 通过下标取数据
    • 取出来是什么类型的,就根据这种类型特点来访问
let arr = ['刘德华', '张学友', '黎明', '郭富城', 'pink老师', 10]
// 2. 使用数组  数组名[索引号] 从0
// console.log(arr)
console.log(arr[0]) // 刘德华
console.log(arr[4])
// 3. 数组长度 =  索引号 + 1 
console.log(arr.length)  // 6
  1. 一些术语

    • 元素:数组中保存的每个数据都叫数组元素
    • 下标:数组中数据的编号
    • 长度:数组中数据的个数,通过数组的length属性获得

小结

  1. 使用数组有什么好处?

    数组可以保存多个数据

  2. 数组字面量用什么表示?

    [] 中括号

数组的概念

  • 数组:(Array)是一种可以按顺序保存数据的数据类型。

  • 为什么要数组?

    • 思考:如果我想保存一个班里所有同学的姓名怎么办?
    • 场景:如果有多个数据可以用数组保存起来,然后放到一个变量中,管理非常方便

数组详细解释:数组是指一组数据的集合,其中每个数据被称作元素,在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的优雅方式。

//普通变量一次只能存储一个值
var num = 10;
//数组一次可以存储多个值
var arr =  [1,2,3,4,5];

数组的基本使用

声明语法(创建数组)

JS中创建数组有两种方式:

  • 利用new创建数组
  • 利用数组字面量创建数组
利用new创建数组
let 数组名 = new Array();
let arr = new Array() // 创建一个新的空数组
let arr1 = new Array(1, 'pink老师', 3) // 创建一个有数据的数组
利用数组字面量创建数组(使用最多)
//1. 利用数组字面量方式创建空的数组
let 数组名 = []
//2.利用数组字面量方式创建带初始值的数组
let 数组名 = ['小明', '小刚', 3]
  • 数组中字面量是方括号[]
  • 声明数组并赋值称为数组的初始化

注意:

  • 数组是按顺序保存,所以每个数据都有自己的编号
  • 计算机中的编号从0开始,所以小明的编号为0,小刚编号为1,以此类推
  • 在数组中,数据的编号也叫索引或下标
  • 数组可以存储任意类型的数据(例如字符串,数字,布尔值等)

取值语法

  • 取值语法:数组名[下标]
  • 通过下标取数据
  • 取出来是什么类型的,就根据这种类型特点来访问
  • 元素:数组中保存的每个数据都叫数组元素
  • 下标:数组中数据的编号(从0开始)
  • 长度:数组中数据的个数,通过数组的length属性获得
let arr = ['小白', '小黑', '大黄']
  索引号     0       1       2

数组可以通过索引来访问、设置、修改对应的数组元素,我们可以通过“数组名[索引]”的形式来获取数组中的元素。 这里的访问就是获取得到的意思。

//定义数组
let arr = [1,2,3]
// 获取数组中的第2个元素
alert(arr[1]) // 2
alert(arr[3]) // undefined

遍历数组

用循环把数组中每个元素都访问到,一般会用for循环遍历

  • 问:数组中的每一项我们怎么取出来?

    答:可以通过“数组名[索引号]”的方式一项项的取出来

var arr = ['red', 'green', 'blue'];
console.log(arr[0]); // red
console.log(arr[1]); // green
console.log(arr[2]); // blue
  • 问:怎么把数组里面的元素全部取出来?

    规律:从代码中我们可以发现,从数组中取出每一个元素时,代码是重复的,有所不一样的是索引值在递增。

    答案:循环

    遍历数组:就是把数组的元素从头到尾访问一次

    通过循环来遍历数组里面的元素

<script>
  let arr = [2, 6, 1, 77, 52, 25, 7]
  //for里面的i是计数器,当索引号使用,arr[i]是数组元素第i个数组元素
  for (let i = 0; i < arr.length; i++) {
      //arr.length  就是数组的长度
      console.log(arr[i])
  }
</script>

操作数组

数组本质是数据集合, 操作数据无非就是 增 删 改 查

语法:

image.png

操作数组-新增

常用
  • 数组.push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度

    语法: arr.push(元素1, ..., 元素n)

  • arr.unshift(新增的内容) 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度

    语法: arr.unshift(元素1, ..., 元素n)

可以通过修改length长度以及索引号增加数组元素

不常用,了解

1. 通过修改length长度新增元素

  • 可以通过修改 length 长度来实现数组扩容的目的
  • length属性是可读写的
<script>
    //  新增数组元素 修改length长度 
    let arr = ['red', 'green', 'blue', 'pink'];
    console.log(arr.length) // 4
    arr.length = 7 // 把我们数组的长度修改为了 7  里面应该有7个元素,其中索引号4,5,6的空间没有给值,就是声明变量未给值,默认值就是undefined.
    console.log(arr)
    console.log(arr[4]) // undefined
    console.log(arr[5]) // undefined
    console.log(arr[6]) // undefined
</script>

2. 通过修改数组索引新增数组元素

  • 可以通过修改数组索引的方式追加数组元素
  • 不能直接给数组名赋值,否则会覆盖掉以前的数据
<script>
    // 新增数组元素 修改索引号 追加数组元素
    let arr1 = ['red', 'green', 'blue']
    arr1[3] = 'pink'
    console.log(arr1)
    arr1[4] = 'hotpink'
    console.log(arr1)
    arr1[0] = 'yellow' // 这里是替换原来的数组元素
    console.log(arr1)
    arr1 = '有点意思'
    console.log(arr1) // 不要直接给 数组名赋值 否则里面的数组元素都没有了
</script>

操作数组-删除

  • 数组.pop() 方法从数组中删除最后一个元素,并返回该元素的值

    语法:arr.pop()

  • 数组.shift() 方法从数组中删除第一个元素,并返回该元素的值

    语法:arr.shift()

  • 数组.splice() 方法 删除指定元素

    语法:arr.splice(起始位置索引号start, 删除几个元素deleteCount)

    start 起始位置: 指定修改的开始位置(从0计数)

    deleteCount: 表示要移除的数组元素的个数;

    可选的。如果省略则默认从指定的起始位置删

除到最后

需求使用场景:

  1. 随机抽奖,中奖的用户就需要从数组里面删除,不允许重复抽奖

  2. 点击删除按钮,相关的数据会从商品数据中删除

数组案例

案例:筛选数组

<script> 
    let arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7]
    let newarr = []
    for (let i = 0; i <= arr.length; i++) {
        if (arr[i] >= 10) {
            newarr.push(arr[i])
        }
    }
    console.log(newarr);
</script>

冒泡排序

它重复的走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。 image.png

<script>
    // 冒泡排序
    let arr = [4, 1, 2, 3, 5]
    for (let i = 0; i < arr.length - 1; i++) { // 外层循环管-趟数 注意五个数据,比较4趟,arr.length=5,又是从0开始的,所以是0-3,i要小于 arr.length-1
      for (let j = 0; j < arr.length - i - 1; j++) { // 里面的循环管 每一趟的交换次数
        // 内部交换2个变量的值 前一个和后面一个数组元素相比较
        if (arr[j] > arr[j + 1]) {
          //let temp = arr[j]
          //arr[j] = arr[j + 1]
          //arr[j + 1] = temp
          //也可以这样简写
          [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
        }
      }
    }
    console.log(arr);
</script>

8. JavaScript 函数

函数的概念

  1. 为什么需要函数

    可以实现代码复用,提高开发效率

  2. 函数是什么

    函数 function,是被设计为执行特定任务的代码块

  • 说明:

    函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势是有利于精简代码方便复用

    比如我们前面使用的 alert() 、 prompt() 和 console.log() 都是一些 js 函数,只不过已经封装好了,我们直接使用的

定义:在JS里面,可能会定义非常多的相同代码或者功能相似的代码,这些代码可能需要大量重复使用。虽然for循环语句也能实现一些简单的重复操作,但是比较具有局限性,此时我们就可以使用JS中的函数

函数:就是封装了一段可被重复调用执行的代码块。目的:可以实现大量代码的重复使用。

函数的使用

函数在使用时分为两步:声明函数和调用函数。

声明函数

// 声明函数
function 函数名() {
    //函数体代码
}

//eg
function sayHi() {
    console.log('hi~');
}

函数名命名规范

  • 和变量命名基本一致
  • 尽量小驼峰式命名法
  • 前缀应该为动词
  • 命名建议:常用动词约定(由于函数一般是为了实现某个功能才定义的,所以通常我们将函数名命名为动词,比如 getSum)

image.png

调用函数

<script>
  // 调用函数
  函数名();//// 通过调用函数名来执行函数体代码
</script>
  • 口诀:函数不调用,自己不执行。

注意:声明(定义)函数本身并不会执行代码,只有调用函数时才会执行函数体代码,使用 () 调用函数。

函数体

函数体是函数的构成部分,它负责将相同或相似代码“包裹”起来,直到函数调用时函数体内的代码才会被执行。函数的功能代码都要写在函数体当中。

image.png

函数的封装

  • 函数的封装是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口
  • 简单理解:封装类似于将电脑配件整合组装到机箱中 ( 类似快递打包)

image.png

前两小结总结

  1. 函数是用那个关键字声明的?

    function

  2. 函数不调用会执行吗?如何调用函数?

    函数不调用自己不执行

    调用方式: 函数名()

  3. 函数的复用代码和循环重复代码有什么不同?

    循环代码写完即执行,不能很方便控制执行位置

    函数随时调用,随时执行,可重复调用

函数传参

  • 思考:这样的函数只能求 10 + 20, 这个函数功能局限非常大 image.png

  • 解决办法:把要计算的数字传到函数内

  • 结论:

    • 若函数完成功能需要调用者传入数据,那么就需要用有参数的函数

    • 这样可以极大提高函数的灵活性

声明语法

function 函数名(参数列表[形参1, 形参2 , 形参3...]) { 函数体 }

参数列表

  • 传入数据列表
  • 声明这个函数需要传入几个数据
  • 多个数据用逗号隔开

调用语法

函数名(传递的参数列表[实参1, 实参2, 实参3...]);

  • 调用函数时,需要传入几个数据就写几个,用逗号隔开

其他

  • 形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数)
  • 实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数)
  • 形参可以理解为是在这个函数内声明的变量(比如 num1 = 10)实参可以理解为是给这个变量赋值
  • 开发中尽量保持形参和实参个数一致
  • 我们曾经使用过的 alert('打印'), parseInt('11'), Number('11') 本质上都是函数调用的传参

具体说明如下:

形参和实参

声明函数时,可以在函数名称后面的小括号中添加一些参数,这些参数被称为形参,而在调用该函数时,同样也需要传递相应的参数,这些参数被称为实参

image.png 参数的作用 : 在函数内部某些值不能固定,我们可以通过参数在调用函数时传递不同的值进去。

// 带参数的函数声明
function 函数名(形参1, 形参2 , 形参3...) { // 可以定义任意多的参数,用逗号分隔
    // 函数体
}

// 带参数的函数调用
函数名(实参1, 实参2, 实参3...);

注意:在JavaScript中,形参的默认值是undefined。

函数参数的传递过程

  1. 调用的时候实参值是传递给形参的

  2. 形参简单理解为:不用声明的变量

  3. 实参和形参的多个参数之间用逗号(,)分隔

函数形参和实参个数不匹配问题

image.png 注意:在JavaScript中,形参的默认值是undefined。

function sum(num1, num2) {
    console.log(num1 + num2);
}
sum(100, 200); // 形参和实参个数相等,输出正确结果
sum(100, 400, 500, 700); // 实参个数多于形参,只取到形参的个数
sum(200); // 实参个数少于形参,多的形参定义为undefined,结果为NaN

小结

  • 函数传递参数的好处是?

    可以极大的提高了函数的灵活性

  • 函数参数可以分为那两类?怎么判断他们是那种参数?

    • 函数参数可以分为形参和实参
    • 函数声明时,函数名小括号里面的是形参,形式上的参数
    • 函数调用时,函数名小括号里面的是实参,实际的参数
    • 尽量保持形参和实参的个数一致
  • 参数中间用什么符号隔开?

    逗号

  • 函数可以带参数也可以不带参数
  • 形参的个数可以和实参个数不匹配,但是结果不可预计,我们尽量要匹配

参数默认值

  • 形参: 可以看做变量,但是如果一个变量不给值,默认是什么?

    undefined

  • 但是如果做用户不输入实参,则undefined + undefined 结果是什么?

    NaN

  • 我们可以改进下,用户不输入实参,可以给 形参默认值,可以默认为 0, 这样程序更严谨,可以如下操作: image.png

说明:这个默认值只会在缺少实参参数传递时 才会被执行,所以有参数会优先执行传递过来的实参, 否则默认为undefined

函数的返回值

  • 提问:什么是函数?

    函数是被设计为执行特定任务的代码块

  • 提问:执行完特定任务之后,然后呢?

    把处理结果返回给调用者

  • 有返回值函数的概念:

    当调用某个函数,这个函数会返回一个结果出来,这就是有返回值的函数

  • 其实我们前面已经接触了很多的函数具备返回值

    let result = prompt('请输入你的年龄')

  • 当然有些函数,则没有返回值

    alert('我是弹框,不需要返回值)

  • 所以要根据需求,来设定需不需要返回值

  • 当函数需要返回数据出去时,用return关键字

return 语句

有的时候,我们会希望函数将值返回给调用者,此时通过使用return 语句就可以实现。

return 语句的语法格式如下:

// 声明函数
function 函数名(){
    ...
    return 需要返回的值;
}
// 调用函数
函数名(); // 此时调用函数就可以得到函数体内return 后面的值
  • 在函数体中使用 return 关键字能将内部的执行结果交给函数外部使用
  • return 后面代码不会再被执行,会立即结束当前函数,所以 return 后面的数据不要换行写
  • 函数可以没有 return,这种情况函数默认返回值为 undefined
  • return 只能返回一个值。如果用逗号隔开多个值,以最后一个为准。

break ,continue ,return 的区别

  • break :结束当前的循环体(如 for、while、switch)
  • continue :跳出本次循环,继续执行下次循环(如 for、while)
  • return :不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码

image.png

小结

  1. 为什么要让函数有返回值

    • 函数执行后得到结果,结果是调用者想要拿到的(一句话,函数内部不需要输出结果,而是返回结果)
    • 对执行结果的扩展性更高,可以让其他的程序使用这个结果
  2. 函数有返回值用那个关键字? 有什么注意事项呢?

    • 语法:return 数据
    • return后面不接数据或者函数内不写return,函数的返回值是undefined
    • return能立即结束当前函数, 所以 return 后面的数据不要换行写

函数细节补充

  • 两个相同的函数后面的会覆盖前面的函数

  • 在Javascript中 实参的个数和形参的个数可以不一致

    • 如果形参过多 会自动填上undefined (了解即可)
    • 如果实参过多 那么多余的实参会被忽略 (函数内部有一个arguments,里面装着所有的实参)
  • 函数一旦碰到return就不会在往下执行了 函数的结束用return

arguments的使用

当我们不确定有多少个参数传递的时候,可以用 arguments 来获取。在 JavaScript 中,arguments 实际上它是当前函数的一个内置对象。所有函数都内置了一个 arguments 对象,arguments 对象中存储了传递的所有实参。

arguments展示形式是一个伪数组,因此可以进行遍历。伪数组具有以下特点:

  • 具有 length 属性
  • 按索引方式储存数据
  • 不具有数组的 push , pop 等方法
//利用函数求任意个数的最大值
function maxValue() {
    var max = arguments[0];
    for (var i = 0; i < arguments.length; i++) {
        if (max < arguments[i]) {
            max = arguments[i];
        }
    }
    return max;
}
console.log(maxValue(2, 4, 5, 9));
console.log(maxValue(12, 4, 9));

作用域

作用域

通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域

作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。

简单来说,Javascript作用域就是代码名字(变量)在某个范围内起作用和效果。目的是为了提高代码的可靠性,更重要的是减少命名冲突。

JavaScript(es6前)中的作用域有两种:局部作用域和全局作用域

image.png

//全局作用域
var num = 10;//num就是一个全局变量
console.log(num);

function fn() {
    //局部作用域
    var num1 = 20;//num1就是局部变量,只能在函数内部使用
    console.log(num1);
}
fn();

全局作用域

作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件。

局部作用域(函数作用域)

在函数内部就是局部作用域 这个代码的名字只在函数内部起效果和作用

变量的作用域

在JavaScript中,根据作用域的不同,变量可以分为两种:全局变量和局部变量

image.png

变量有一个坑, 特殊情况:

如果函数内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐

但是有一种情况,函数内部的形参可以看做是局部变量。

全局变量
  • 在全局作用域下声明的变量(在函数外部定义的变量)。
  • 全局变量在代码的任何位置都可以使用
  • 在全局作用域下 let 声明的变量 是全局变量
  • 特殊情况下,在函数内不使用 let 声明的变量也是全局变量(不建议使用),也就是说如果在函数内部 没有声明直接赋值的变量也属于全局变量。
let num = 10 // num就是一个全局变量
console.log(num)

function fn() {
  console.log(num)

}
fn()
局部变量:在局部作用域下声明的变量(在函数内部定义的变量)
  • 局部变量只能在该函数内部使用
  • 在函数内部 let 声明的变量是局部变量
  • 函数的形参实际上就是局部变量
function fun(aru) {
    let num1 = 10 // num1就是局部变量 只能在函数内部使用
    num2 = 20
}
fun()
全局变量和局部变量的区别
  • 全局变量:在任何一个地方都可以使用,只有在浏览器关闭的时候才会被销毁,因此比较占内存资源。
  • 局部变量:只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块执行完毕就会被销毁,因此更节省内存空间。
JS 没有块级作用域

块作用域由 { } 包括。

js中没有块级作用域,es5中js的作用域:全局作用域、局部作用域,现阶段js 没有块级作用域

js 也是在 es6 的时候新增的块级作用域

块级作用域 {} if {} for {}

作用域链

  • 只要是代码,就至少有一个作用域
  • 写在函数内部的局部作用域
  • 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
  • 变量访问原则:在能够访问到的情况下,先局部,局部没有在找全局(也就是:就近原则)
  • 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链

作用域链:采取就近原则的方式来查找变量最终的值。

<script>
    // 作用域链:内部函数访问外部函数的变量,采取的是链式查找的方式来决定取那个值 这种结构我们称为作用域链   就近原则
    var num = 10;  // 全局变量
    function fn() { // 外部函数
      var num = 20;  // 局部变量
      function fun() { // 内部函数
        console.log(num);
      }
      fun();
    }
    fn();
</script>

function f1(){
  var num=123;
  function f2(){
    console.log(num); // 站在目标触发,一层一层的往外找
  }
  f2();
}
var num=456;
f1(); //  最后输出的是123;

小结

  1. JS 中作用域分为哪2种?

    全局作用域。函数外部或者整个script 有效

    局部作用域。也称为函数作用域,函数内部有效

  2. 根据作用域不同,变量分为哪2种?

    全局变量

    局部变量

  3. 有一种特殊情况是全局变量是那种?我们提倡吗?

    局部变量或者块级变量 没有let 声明直接赋值的当全局变量看

    我们强烈不提倡

    还有一种特殊情况,函数内部的形参可以当做局部变量看

匿名函数

函数可以分为(函数的两种声明方式):具名函数(自定义函数方式/命名函数)、匿名函数

具名函数

利用函数关键字 function 自定义函数方式。

// 声明定义方式
function fn() {...}
// 调用
fn();
  • 因为有名字,所以也被称为命名函数
  • 调用函数的代码既可以放到声明函数的前面,也可以放在声明函数的后面

匿名函数

function() {}

没有名字的函数, 无法直接使用。

使用方式:函数表达式、立即执行函数

函数表达式

将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为函数表达式

  • 语法:let fn = function() {}
  • 调用:fn()
  • 注意:
    • 其中函数的形参和实参使用跟具名函数一致。
    • 这个fn 是变量名,不是函数名,里面存储的是一个函数
    • 函数表达式方式跟声明变量差不多,只不过变量里面存的是值,而函数表达式里面存的是函数
    • 函数调用的代码必须写到函数体后面
立即执行函数
  • 场景介绍: 避免全局变量之间的污染
  • 语法:
    • (function () {})();
    • (function () { }());
  • 注意: 多个立即执行函数要用 ; 隔开,要不然会报错
总结
  1. 立即执行函数有什么作用?

    防止变量污染

  2. 立即执行函数需要调用吗? 有什么注意事项呢?

    无需调用,立即执行,其实本质已经调用了

    多个立即执行函数之间用分号隔开

9. JavaScript 对象

什么是对象

先总结:

  1. 对象是什么?

    • 对象是一种数据类型
    • 无序的数据的集合
  2. 对象有什么特点?

  • 无序的数据的集合
  • 可以详细的描述描述某个事物

再具体说明:

现实生活中:万物皆对象,对象是一个具体的事物,看得见摸得着的实物。例如,一本书、一辆汽车、一个人可以是“对象”,一个数据库、一张网页、一个与远程服务器的连接也可以是“对象”。

在 JavaScript 中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。

对象是由属性和方法组成的。

  • 属性:事物的特征(或信息),在对象中用属性来表示(常用名词),比如 手机尺寸、颜色、重量等…
  • 方法:事物的行为(或功能),在对象中用方法来表示(常用动词),比如 手机打电话、发短信、玩游戏…,其本质是函数。

image.png

  • 属性都是成 对出现的,包括属性名和值,它们之间使用英文 : 分隔
  • 多个属性之间使用英文 , 分隔
  • 属性就是依附在对象上的变量(外面是变量,对象内是属性)
  • 属性名可以使用 "" 或 '',一般情况下省略,除非名称遇到特殊符号如空格、中横线等
  1. 方法是由方法名和函数两部分构成,它们之间使用 : 分隔
  2. 多个属性之间使用英文 , 分隔
  3. 方法是依附在对象中的函数
  4. 方法名可以使用 "" 或 '',一般情况下省略,除非名称遇到特殊符号如空格、中横线等
为什么需要对象

保存一个值时,可以使用变量,保存多个值(一组值)时,可以使用数组。如果要保存一个人的完整信息呢?

例如,将“张三疯”的个人的信息保存在数组中的方式为:

var arr = ['张三疯', '男', 128,154];

JS 中的对象表达结构更清晰,更强大。张三疯的个人信息在对象中的表达结构如下:

image.png

对象使用

对象声明(创建对象)

在 JavaScript 中,现阶段我们可以采用三种方式创建对象(object):

  • 利用字面量创建对象 {}是对象字面量
  • 利用 new Object 创建对象
  • 利用构造函数创建对象
利用字面量创建对象

对象字面量:就是花括号 { } 里面包含了表达这个具体事物(对象)的属性和方法。

{ } 里面采取键值对的形式表示

  • 键:相当于属性名
  • 值:相当于属性值,可以是任意类型的值(数字类型、字符串类型、布尔类型,函数类型等)
var star = {//多个属性或者方法中间用逗号隔开
    name : 'pink',
    age : 18,
    sex : '男',
    sayHi : function(){//方法冒号后面跟的是一个匿名函数
        alert('大家好啊~');
    }
}
console.log(star.name) // 调用名字属性
console.log(star['name']) // 调用名字属性
star.sayHi(); // 调用 sayHi 方法,注意,一定不要忘记带后面的括号

对象的调用

  • 对象里面的属性调用 : 对象.属性名 ,这个小点 . 就理解为“ 的 ”
  • 对象里面属性的另一种调用方式 : 对象['属性名'],注意方括号里面的属性必须加引号,我们后面会用
  • 对象里面的方法调用:对象.方法名() ,注意这个方法名字后面一定加括号
变量、属性、函数、方法总结
  • 变量:单独声明赋值,单独存在,使用的时候直接写变量名
  • 属性:对象里面的变量称为属性,不需要声明,用来描述该对象的特征,使用的时候必须是 对象.属性
  • 函数:单独存在声明的,单独存在,通过“函数名()”的方式就可以调用
  • 方法:对象里面的函数称为方法,方法不需要声明,使用“对象.方法名()”的方式就可以调用,方法用来描述该对象的行为和功能。
利用new Object创建对象
var andy = new Obect();//创建了一个空的对象
andy.name = 'pink';//追加属性
andy.age = 18;
andy.sex = '男';
andy.sayHi = function(){//追加方法
alert('大家好啊~');
  • Object() :第一个字母大写
  • new Object() :需要 new 关键字
  • 使用的格式:对象.属性 = 值;
  • 利用等号 = 赋值的方法,添加对象的属性额方法
  • 每个属性和方法之间用分号结束
利用构造函数创建对象

为什么需要使用构造函数?前面两种创建对象的方式一次只能创建一个对象,因此我们可以利用函数的方法,重复这些相同的代码,我们就把这个函数称为构造函数,又因为这个函数不一样,里面封装的不是普通代码,而是对象。

构造函数:是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。

在 js 中,使用构造函数要时要注意以下两点:

  • 构造函数用于创建某一类对象,其首字母要大写
  • 构造函数要和 new 一起使用才有意义
//构造函数的语法格式
function 构造函数名() {
    this.属性 = 值;
    this.方法 = function() {}
}
new 构造函数名();

//具体实例
function Person(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.sayHi = function() {
        alert('我的名字叫:' + this.name + ',年龄:' + this.age + ',性别:' + this.sex);
    }
}
var bigbai = new Person('大白', 100, '男');
var smallbai = new Person('小白', 21, '男');
console.log(bigbai.name);
console.log(smallbai.name);

注意

  1. 构造函数约定首字母大写。
  2. 函数内的属性和方法前面需要添加 this ,表示当前对象的属性和方法。
  3. 构造函数中不需要 return 返回结果。
  4. 当我们创建对象的时候,必须用 new 来调用构造函数。
  5. 我们只要new 构造函数名() 调用函数,就创建一个对象
构造函数和对象
//构造函数和对象
//构造函数 明星 泛指的是某一大类
function Star(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.sayHi = function() {
        alert('我的名字叫:' + this.name + ',年龄:' + this.age + ',性别:' + this.sex);
    }
}
//对象 是一个具体的事物 刘德华
var ldh = new Star('刘德华', 18, '男');//调用函数返回的是一个对象
  • 构造函数,如 Stars(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类(class)
  • 创建对象,如 new Stars(),特指某一个,利用构造函数通过 new 关键字创建对象的过程我们也称为对象实例化

image.png

new关键字

image.png

对象的操作

对象本质是无序的数据集合, 操作数据无非就是 增 删 改 查

image.png

属性

  • 声明对象,并添加了若干属性后,可以使用 . 获得对象中属性对应的值,称之为属性访问。

  • 语法

    • 对象名.属性
    • 对象名['属性'] 单引号和双引号都阔以
  • 简单理解就是获得对象里面的属性值

  • 总结:

    没有必要的时候直接使用点语法, 在需要解析变量的时候使用 [] 语法

方法

  • 声明对象,并添加了若干方法后,可以使用 . 调用对象中函数,称之为方法调用。
  • 语法: 对象名.方法()
  • 对象方法可以传递参数,也可以添加形参和实参,跟函数使用方法基本一致

image.png

语法:对象名.属性 = 新值

语法:对象名.新属性 = 新值

删(了解)

语法:delete 对象名.属性

遍历对象

for...in 语句用于对数组或者对象的属性进行循环操作。

var obj = {
    name: 'pink',
    age: 18
}
for (let k in obj) {
    console.log(k); // 这里的 k 是属性名
    console.log(obj[k]); // 这里的 obj[k] 是属性值
}
  • 一般不用for in这种方式遍历数组、主要是用来遍历对象
  • for in语法中的 k 是一个变量, 在循环的过程中依次代表对象的属性名
  • 由于 k 是变量, 所以必须使用 [ ] 语法解析
  • 一定记住: k 是获得对象的属性名, 对象名[k] 是获得 属性值

小结

  1. 对象可以让代码结构更清晰
  2. 对象复杂数据类型object。
  3. 本质:对象就是一组无序的相关属性和方法的集合。
  4. 构造函数泛指某一大类,比如苹果,不管是红色苹果还是绿色苹果,都统称为苹果。
  5. 对象实例特指一个事物,比如这个苹果、正在给你们讲课的pink老师等。
  6. for...in 语句用于对对象的属性进行循环操作。

10. 扩展阅读

1. 解释型语言和编译型语言

能够知道解释性语言和编译型语言的特点

概述

计算机不能直接理解任何除机器语言以外的语言,所以必须要把程序员所写的程序语言翻译成机器语言才能执行程序。程序语言翻译成机器语言的工具,被称为翻译器。

image.png

  • 翻译器翻译的方式有两种:一个是编译,另外一个是解释。两种方式之间的区别在于翻译的时间点不同
  • 编译器是在代码执行之前进行编译,生成中间代码文件
  • 解释器是在运行时进行及时解释,并立即执行(当编译器以解释方式运行的时候,也称之为解释器)

注意:js属于解释型语言,java属于编译型语言

image.png

执行过程

image.png 类似于请客吃饭:

  • 编译语言:首先把所有菜做好,才能上桌吃饭
  • 解释语言:好比吃火锅,边吃边涮,同时进行

2. 关键字、保留字、标识符、表达式、语句

image.png

标识(zhi)符

标识(zhi)符:就是指开发人员为变量、属性、函数、参数取的名字。

标识符不能是关键字或保留字。

关键字

关键字:是指 JS本身已经使用了的字,不能再用它们充当变量名、方法名。

包括:break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with 等。

保留字

保留字:实际上就是预留的“关键字”,意思是现在虽然还不是关键字,但是未来可能会成为关键字,同样不能使用它们当变量名或方法名。

包括:boolean、byte、char、class、const、debugger、double、enum、export、extends、fimal、float、goto、implements、import、int、interface、long、mative、package、private、protected、public、short、static、super、synchronized、throws、transient、volatile 等。

注意:如果将保留字用作变量名或函数名,那么除非将来的浏览器实现了该保留字,否则很可能收不到任何错误消息。当浏览器将其实现后,该单词将被看做关键字,如此将出现关键字错误。

表达式和语句

  • 表达式:

    表达式是可以被求值的代码,JavaScript 引擎会将其计算出一个结果。

    x = 7

    num++

  • 语句:

    语句是一段可以执行的代码。

    比如: prompt() 可以弹出一个输入框,还有 if语句 for 循环语句等等

  • 表达式和语句的区别

    • 表达式:因为表达式可被求值,所以它可以写在赋值语句的右侧。

      表达式 num = 3 + 4

    • 语句:而语句不一定有值,所以比如 alert() for和break 等语句就不能被用于赋值。

      语句 alert() 弹出对话框 console.log() 控制台打印输出

某些情况,也可以把表达式理解为表达式语句,因为它是在计算结果,但不是必须的成分 (例如continue语句)

3. JS 命名规范以及语法格式

变量命名规则与规范

规则:必须遵守,不遵守报错 (法律层面)

规范:建议,不遵守不会报错,但不符合业内通识 (道德层面)

  1. 规则:

    • 不能用关键字

      关键字:有特殊含义的字符,JavaScript 内置的一些英语词汇。例如:let、var、if、for等

      (不能 是关键字、保留字。例如:var、for、while)

    • 只能用下划线、字母、数字、$ 组成,且数字不能开头

      字母(A-Za-z)、数字(0-9)、下划线(_)、美元符号( $ )组成

    • 字母严格区分大小写,如 Age 和 age 是不同的变量

  2. 规范:

    • 起名要有意义

    • 遵守小驼峰命名法

      第一个单词首字母小写,后面每个单词首字母大写。例:userName

函数名命名规范

  • 和变量命名基本一致
  • 尽量小驼峰式命名法
  • 前缀应该为动词
  • 命名建议:常用动词约定(由于函数一般是为了实现某个功能才定义的,所以通常我们将函数名命名为动词,比如 getSum)

image.png

标识符命名规范

  • 变量、函数的命名必须要有意义
  • 变量的名称一般用名词
  • 函数的名称一般用动词

操作符规范

//操作法的左右两侧各保留一个空格
for (var i = 1; i <= 5; i++) {
    if (i == 3) {
        break; // 直接退出整个for 循环,跳到整个for下面的语句
    }
    console.log('我正在吃第' + i + '个包子呢');
}

单行注释规范

break; // 单行注释前面注意有个空格

其他规范

if (i == 3) {
   break; // 直接退出整个for 循环,跳到整个for下面的语句
}

4. 简单类型与复杂类型

简单类型与复杂类型

简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。

  • 值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型string ,number,boolean,undefined,null

  • 引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型;通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等

堆和栈

堆栈空间分配区别:

  1、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;

简单数据类型存放到栈里面

  2、堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。

复杂数据类型存放到堆里面

image.png 注意:JavaScript中没有堆栈的概念,通过堆栈的方式,可以让大家更容易理解代码的一些执行方式,便于将来学习其他语言。

简单类型的内存分配

  • 值类型(简单数据类型): string ,number,boolean,undefined,null
  • 值类型变量的数据直接存放在变量(栈空间)中
  • 注意:简单数据类型null返回的是一个空的对象 object

image.png

复杂类型的内存分配

  • 引用类型(复杂数据类型):通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
  • 引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中

image.png

简单类型传参

函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。

function fn(a) {
    a++;
    console.log(a);
}
var x = 10;
fn(x);
console.log(x);

复杂类型传参

函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。

function Person(name) {
    this.name = name;
}
function f1(x) { // x = p
    console.log(x.name); // 2. 这个输出什么 ? 刘德华
    x.name = "张学友";
    console.log(x.name); // 3. 这个输出什么 ? 张学友
}
var p = new Person("刘德华");
console.log(p.name); // 1. 这个输出什么 ? 刘德华
f1(p);
console.log(p.name); // 4. 这个输出什么 ? 张学友

5. JavaScript 预解析

预解析

//1问
console.log(num);  // 结果是多少?报错
//2问
console.log(num1);  // 结果是多少?undefined
var num1 = 10;   
//3问
fn(); // 结果是多少? 11
function fu() {
    console.log(11);
}
//4问
fun(); // 结果是多少?报错
var fun = function() {
    console.log(22);
}

JavaScript代码是由浏览器中的JavaScript解析器来执行的,JavaScript解析器(js引擎)在运行JavaScript代码的时候分为两步,预解析和步代码执行。

  • 预解析:在当前作用域下, JS 代码执行之前,浏览器(js引擎)会把js里面所有的 var 和 function 在内存中进行提前声明或者定义(提升到当前作用域的最前面)。
  • 代码执行: 按照代码书写的顺序从上到下执行JS语句。

预解析分为:变量预解析(变量提升)和函数预解析(函数提升)

变量预解析(变量提升)

变量提升:就是把所有的变量声明提升到当前的作用域最前面,注意不提升赋值操作

函数预解析(函数提升)

函数提升:就是把所有的函数声明提升到当前作用域的最前面,但是不调用函数

//预解析案列
var num = 10;
fun();
function fun() {
    console.log(num); // 结果是undefined
    var num = 20;
}
//相当于执行了以下操作
var num;
function fun() {
    var num;
    console.log(num);
    num = 20;
}
num = 10
fun();
//预解析案列
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
    var a = b = c = 9;
    console.log(a);
    console.log(b);
    console.log(c);
}
//var a = b = c = 9;相当于var a = 9;b = 9;c = 9;
//b和c直接赋值没有var声明当全局变量看
//结果是:9 9 9 9 9 报错

6. 变量声明 let var const

let和var的区别

let 和 var 区别:

在较旧的JavaScript,使用关键字 var 来声明变量 ,而不是 let。

var 现在开发中一般不再使用它,只是我们可能再老版程序中看到它。

let 为了解决 var 的一些问题。

var 声明:

  • 可以先使用 在声明 (不合理)
  • var 声明过的变量可以重复声明(不合理)
  • 比如变量提升、全局变量、没有块级作用域等等

结论:

var 就是个bug,别迷恋它了,以后声明变量我们统一使用 let

var let const应该用哪个?

  • 变量声明有三个 var let 和 const,我们应该用那个呢?

    首先var 先排除,老派写法,问题很多,可以淘汰掉…

    let or const ?

    建议: const 优先,尽量使用const,原因是:

    • const 语义化更好
    • 很多变量我们声明的时候就知道他不会被更改了,那为什么不用 const呢?
    • 实际开发中也是,比如react框架,基本const
  • 如果你还在纠结,那么我建议:

    • 有了变量先给const,如果发现它后面是要被修改的,再改为let

const使用注意事项

  • const 声明的值不能更改,而且const声明变量的时候需要里面进行初始化
  • 但是对于引用数据类型,const声明的变量,里面存的不是 值,不是值,不是值,是 地址。 image.png

image.png

为什么const声明的对象可以修改里面的属性?

因为对象是引用类型,里面存储的是地址,只要地址不变,就不会报错

建议数组和对象使用 const 来声明

什么时候使用let声明变量?

如果基本数据类型的值或者引用类型的地址发生变化的时候,需要用let,比如 一个变量进行加减运算,比如 for循环中的 i++

笔记来自