整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

HTML 简介

HTML(HyperText Markup Language,中文:超文本标记语言)是一种用于创建网页结构和内容的标记语言。它由一系列标签组成,这些标签描述了网页中的各个元素和其它相关信息。通过使用HTML标签和属性,开发人员可以定义文本、图像、链接、表格、表单等元素,并控制它们的外观和行为。本文主要介绍HTML的基本概念、历史背景和用途。


参考文档:https://www.cjavapy.com/article/3297/


HTML实例:


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CJAVAPY编程之路(cjavapy.com)</title>
</head>
<body>
 
<h1>我的第一个标题</h1>
 
<p>我的第一个段落。</p>
 
</body>
</html>


HTML文档的后缀名可以是.html或.htm,都可以使用,没有区别。


注意:对于中文网页需要使用<meta charset="utf-8"> 声明编码,否则会出现乱码。有些浏览器(如 360 浏览器)会设置 GBK 为默认编码,则你需要设置为<meta charset="gbk"> 。


1、HTML的基本概念


1)标签(Tag)


HTML使用标签来定义网页中的各个元素。标签通常以尖括号< >的形式出现,如<p>表示段落,<img>表示图像等。标签可以包含属性,用于提供额外的信息或控制元素的行为。


2)元素(Element)


一个完整的HTML元素由开始标签、内容和结束标签组成。例如,<p>这是一个段落</p>就是一个完整的段落元素。


3)属性(Attribute)


HTML标签可以具有属性,用于提供元素的额外信息或控制元素的行为。属性以键值对的形式出现,例如<img src="image.jpg">中的src属性指定了图像的源文件。


4)文档结构


一个HTML文档由<html>、<head>和<body>等标签组成。其中,<html>标签用于定义整个HTML文档的根元素,<head>标签用于定义文档的头部信息,如标题和样式表链接,<body>标签用于定义文档的主体内容。


5)块级元素和内联元素


HTML元素可以被分类为块级元素和内联元素。块级元素以块的形式显示,独占一行或一块空间,如<p>、<div>等。内联元素以行内的方式显示,不会独占一行,如<span>、<a>等。


6)嵌套


HTML元素可以嵌套在其他元素内部,形成一个层次结构。例如,<div>元素可以包含<p>元素,<p>元素可以包含<span>元素。


7)<!DOCTYPE> 声明


HTML文档的开头通常会包含一个DOCTYPE声明,用于指定文档的HTML版本。


例如:


<!DOCTYPE html>
<!DOCTYPE HTML>
<!doctype html>
<!Doctype Html>


2、HTML与Web 浏览器


HTML(HyperText Markup Language)是一种用于创建网页结构和内容的标记语言,而Web浏览器(如谷歌浏览器,Internet Explorer,Firefox,Safari)是用于显示和解释HTML文档的应用程序。Web浏览器通过解析HTML文档,将其转换为可视化的网页。浏览器会读取HTML文档中的标签和内容,并根据这些标签和内容的定义,渲染出网页的结构和样式。HTML提供了各种标签和属性,用于定义文本、图像、链接、表格、表单等在网页中的展示和交互方式。浏览器在解析HTML时,会根据标签和属性的定义,将文本显示为段落、标题或其他格式,显示图像、链接,并响应用户的交互操作。


通过HTML和Web浏览器的结合,用户可以在浏览器中访问和浏览各种网页内容,包括网页文本、图像、视频、音频等多媒体元素,并与网页进行交互,如点击链接、填写表单、提交数据等。


大部分浏览器中,直接输出中文会出现中文乱码的情况,需要在头部将字符声明为 UTF-8 或 GBK。


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>
页面标题</title>
</head>
<body>
 
<h1>我的第一个标题</h1>
 
<p>我的第一个段落。</p>
 
</body>
</html>


3、HTML版本及历史背景


HTML有多个版本,每个版本都有不同的特性和改进。


版本

发布时间

HTML

1991

HTML+

1993

HTML 2.0

1995

HTML 3.2

1997

HTML 4.01

1999

XHTML 1.0

2000

HTML5

2014


1)HTML 1.0


HTML 1.0是最早的HTML版本,于1993年发布。它只包含一些基本的标签和属性,用于创建简单的文本和链接。HTML 1.0的目标是定义一种通用的超文本标记语言。


2)HTML 2.0


HTML 2.0于1995年发布,是对HTML 1.0的改进和扩展。它引入了一些新的标签和属性,如图像标签和表格标签,以支持更丰富的内容展示。


3)HTML 3.2


HTML 3.2于1997年发布,是对HTML 2.0的进一步改进。它引入了一些新的标签和属性,如表单标签和框架标签,以支持交互性和页面布局。


4)HTML 4.01


HTML 4.01于1999年发布,是对HTML 3.2的修订和扩展。它引入了更多的标签和属性,如层标签和样式表,以支持更灵活的页面设计和样式控制。


5)XHTML 1.0


XHTML(eXtensible HyperText Markup Language)是基于XML的HTML版本。XHTML 1.0于2000年发布,它严格遵循XML的语法规则,要求所有标签和属性都要正确嵌套和闭合。


6)HTML5


HTML5是HTML的最新版本,于2014年正式发布。HTML5引入了许多新的特性和API,如语义化标签、多媒体支持、Canvas绘图、本地存储等。HTML5还支持响应式设计,以适应不同设备和屏幕尺寸。


4、HTML用途


HTML是构建网页结构和内容的基础语言,它提供了丰富的标签和属性,使得开发者可以创建各种类型的网页,并实现不同的功能和效果。HTML用于定义网页的整体结构,包括标题、段落、列表、标题、导航菜单等元素。通过使用不同的HTML标签和属性,可以将文本、图像、音频、视频等内容组织起来,并构建页面的层次结构。HTML可以用于展示文本内容和多媒体元素,如图像、音频和视频。通过使用适当的HTML标签和属性,可以插入和显示各种类型的媒体内容,从而使网页更加丰富和吸引人。HTML提供了创建表单的标签和元素,可以用于收集用户的输入数据。通过使用表单元素如文本框、复选框、单选按钮和下拉列表等,用户可以输入数据并提交给服务器进行处理。


参考文档:https://www.cjavapy.com/article/3297/

HTML文本格式化通常使用一系列特定的标签来改变文本的外观或结构。这些标签可以控制文本的字体、大小、颜色、对齐方式等,也可以用来标记文本的逻辑结构(如段落、标题、列表等)。除了这些基本的格式化标签,HTML还支持通过CSS(级联样式表)来更精细和灵活地控制文本的格式和样式。


参考文档:https://www.cjavapy.com/article/3306/


1、标题


HTML中,文本格式化和结构化主要通过一系列标签来完成,其中标题(Headings)标签是最常用于定义文本格式的元素之一。HTML提供了六级标题标签,从 <h1> 到 <h6>,<h1> 表示最高级别的标题,而 <h6> 表示最低级别的标题。这些标题标签不仅帮助改善网页的结构和可读性,还对搜索引擎优化(SEO)至关重要,因为搜索引擎使用这些标签来识别网页上的不同部分和内容的层次结构。每个级别的标题都有默认的样式,通常是不同的大小和加粗,以显示它们的层次结构


<h1>这是一个 H1 标题</h1>
<h2>这是一个 H2 标题</h2>
<h3>这是一个 H3 标题</h3>
<h4>这是一个 H4 标题</h4>
<h5>这是一个 H5 标题</h5>
<h6>这是一个 H6 标题</h6>


2、段落与换行


HTML中,文本格式化通常涉及使用特定的标签来控制文本的显示方式。段落和换行是两个基本但非常重要的文本格式化概念。用<p>创建段落,<br>插入换行。


1)段落 (<p> 标签)


<p> 标签自带上下边距,用以区分不同的段落。
<p>这是一个段落。</p>
<p>这是另一个段落。</p>


2)换行 (<br> 标签)


<br> 标签只是简单地添加一个换行点,不添加任何额外的空间或边距,并且通常用于诗歌或地址等需要精确控制换行位置的文本。


这是文本行的开始。<br>这是新的一行,但在同一个段落内。


3、强调文本


使用<em>和<strong>强调文本。HTML中,强调文本通常使用 <em> 和 <strong> 标签来实现。这两个标签既有语义意义,也影响文本的表现形式。


<em> 标签用于表示强调文本,通常表现为斜体,用以表示文本的轻度强调。


<strong> 标签用于表示更强烈的强调,通常表现为加粗,表示文本的高度强调。


<p>This is <em>emphasized</em> text.</p>
<p>This is <strong>strongly emphasized</strong> text.</p>


4、列表


HTML 提供了两种主要的列表类型:有序列表(<ol>)和无序列表(<ul>)。两种类型都使用列表项(<li>)来定义列表中的实际项。


1)有序列表


有序列表以 <ol> 标签开始。每个列表项都放在 <li> 标签内。列表是有序的,也就是每个项目都是编号的。这适用于项目顺序很重要的列表,如食谱或待办事项列表。


<ol>
  <li>第一项</li>
  <li>第二项</li>
  <li>第三项</li>
</ol>


2)无序列表


无序列表以 <ul> 标签开始。像有序列表一样,每个项都放在 <li> 标签内。然而,无序列表中的项目不是编号的。使用圆点符号进行表示。这适用于项目顺序不重要的列表,如购物清单。


<ul>
  <li>苹果</li>
  <li>香蕉</li>
  <li>橙子</li>
</ul>


5、使用示例


<!DOCTYPE html>
<html>
<head>
<title>文本格式化示例</title>
</head>
<body>

<h1>HTML 文本格式化</h1>
<p>这是一个<em>斜体</em>和<strong>加粗</strong>的示例。</p>
<p><u>这段文本下划线</u>和<s>这段文本是删除线</s>。</p>
<p>化学水分子公式为H<sub>2</sub>O,E=mc<sup>2</sup>。</p>

<pre>
这是预格式化文本,
保留了空格和
换行符。
</pre>

<blockquote>这是一个长引用的示例,可能包含多个段落。</blockquote>
<p>这是一个<q>短引用</q>的示例。</p>

<p>使用<code>HTML</code>和<code>CSS</code>进行网页设计。</p>
<p>按<kbd>Ctrl</kbd> + <kbd>C</kbd>复制文本。</p>
<p><samp>这是计算机程序的输出。</samp></p>
<p>在JavaScript中,<var>x</var>可以作为变量。</p>

</body>
</html>


参考文档:https://www.cjavapy.com/article/3306/

. 初识JS

1.1 什么是JS语言

javascript是一种运行在客户端 的脚本语言

客户端: 即接受服务的一端,与服务端相对应,在前端开发中,通常客户端指的就是浏览器。

脚本语言: 也叫解释型语言,特点是执行一行,解释一行,如果发现报错,代码就停止执行。

1.2 JS的三个组成部分

javascript的三个组成部分:ECMAScript、BOM、DOM

ECMAScript: 定义了javascript的语法规范。

BOM: 一套操作浏览器功能的API。

DOM: 一套操作页面元素的API。

1.3 script 标签

1、script标签的书写方式

书写Javascript代码有两种方式,第一种是直接在script标签中书写,第二种是将代码写在js文件中,通过script的src属性进行引入。

直接在script中书写javascript代码:

<!-- type="text/javascript" 可以省略 -->
<script type="text/javascript">
 alert("今天天气真好呀");
</script>

通过script标签引入一个JS文件,需要指定src属性:

<!-- 表示引用了test.js文件,并且script标签内不可以继续写代码 -->
<script src="test.js"></script> 

如果script标签指定了src属性,说明是想要引入一个js文件,这个时候不能继续在script标签中写js代码,即便写了,也不会执行。

2、script标签的书写位置

script标签的书写位置,原则上来说,可以在页面中的任意位置书写。

写在head标签中,style标签之后:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
 <link rel="stylesheet" href="demo.css">
 <!-- 写在这里 -->
 <script src="demo.js"></script>
</head>
<body>
</body>
</html>

浏览器有一个特性,就是在遇到<body>标签时才开始呈现内容。如果在head里面引用js文件的话,意味着必须要等到全部的javascript代码都被下载、解析和执行完成之后,才能开始呈现页面的内容。如果文件数量一旦过多,将会影响页面加载速度,此时页面有可能会在加载完成前一片空白。

写在</body>标签的前面:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
 <link rel="stylesheet" href="demo.css">
</head>
<body>
 <!-- 写在这里 -->
 <script src="demo.js"></script>
</body>
</html>

在解析javascript代码之前,页面的内容已经完全呈现在浏览器当中了,用户会明显感觉页面加载变快了。

1.4 js中输入输出语句

  • console.log 控制台输出日志
  • console.dir 对象的形式打印一个对象
  • document.write 往页面中写入内容
  • alert 弹框警告
  • confirm 确认框
  • prompt 输入框

1.5 注释

不被程序执行的代码。用于程序员标记代码,在后期的修改,以及他人的学习时有所帮助,在JS中,分为单行注释和多行注释以及文档注释。

单行注释

//这是单行注释,只能注释一行

多行注释

/*
 这是多行注释,不能嵌套
*/

文档注释

/**
 * 求圆的面积
 * @param r {number} 圆的半径
 * @returns {number} 圆的面积
 * 这是文档注释
 */
function getArea (r) {
 return Math.PI * r * r;
}

注释的作用

  • 模块划分,方便代码查找和维护
  • 用于解释复杂代码的逻辑,方便维护和后期开发。

2. 变量

变量,可以变化的量,变量是在计算机中存储数据的一个标识符。可以把变量看成存储数据的容器。

变量与字面量:

  • 字面量:10、20、“abc”、true这种从字面上就能看出来类型和值的量叫做字面量。
  • 变量:可以变化的量。

2.1 变量的声明与赋值

// 1- 同时声明并且赋值
var num = 100;
console.log(num); // 100
// 2- 先声明了一个变量,再赋值
var num1;
num1 = 100;
console.log(num1); // 100
// 3- 没有声明变量,直接赋值(可以,但是不推荐)
num2 = 200;
console.log(num2); // 200
// 4- 有变量声明,但是没有赋值(可以,没有赋值,变量的值默认是个undefined)
var num9;
console.log(num9); // undefined
// 5- 既没有声明,也没有赋值,直接用。
console.log(num3); //报错 num3
// 6- 一个 var,逗号分隔 可以同时声明多个变量
var name = "Levi丶",
 age = 18,
 gender = "男";

2.2 变量的命名规则与规范

命名规则(必须遵守):

  • 由字母、数字、下划线、$符号组成,开头不能是数字。
  • 不能使用关键字和保留字
  • 区分大小写

命名规范(建议遵守):

  • 命名要有意义
  • 遵守驼峰命名法。首字母小写,后面单词的首字母需要大写。

2.3 交换两个变量的值

方法一: 声明一个新的变量

// 交换 num1 和 num2的值
var num1 = 11;
var num2 = 22;
var temp;
temp = num1; // num1=11 temp=11
num1 = num2; // num1=22 num2=22
num2 = temp; // temp=11 num2=11

方法二: 不通过声明变量的方式

// 不使用临时变量
var num1 = 11;
var num2 = 22;
// num1 = 11 + 22
num1 = num1 + num2; // num1=33 
// num2 = 33 - 22
num2 = num1 - num2; // num2=11
// num1 = 33 - 11 
num1 = num1 - num2; // num1=22

3. 数据类型

基本数据类型包括了:number、string、boolean、undefined、null

3.1 如何查看数据类型

使用typeof关键字查看数据类型
typeof(name); 
// 括号可以省略
typeof name;

3.2 Number 类型

进制

  • 十进制,我们平时使用的就是十进制,进行运算时,八进制和十六进制的值最终都会转换成十进制。
  • 二进制,计算机当中用的最多的计算方式,数值序列只有0和1
  • 八进制,0开头的数值,数值序列:0-7
  • 十六进制,0x开头的数值,数值序列:0-9、A-F、a-f

浮点数

所谓浮点数,就是该数当中必须包含一个小数点,并且小数点后面至少有一位数字。

科学计数法:

//如何表示0.003和20000?
var num = 3e-3; // 0.003
var num2 = 2e+4; // 20000 

浮点数的精度问题:

0.1 + 0.2 = ? // 0.30000000000000004
0.07 * 100 = ? // 7.000000000000001

浮点数在运算的时候会出现精度丢失的问题,因此在做比较运算的时候,尽量不要用小数进行比较。在第五章的时候会着重讲解这个问题

数值范围

javascript不能表示世界上所有的数,因此在javascript中,数值大小是有一定限制的。
  • Number.MIN_VALUE:5e-324 (js里面能表示最小的数)
  • Number.MAX_VALUE:1.7976931348623157e+308 (js里面能表示最大的数)
  • Infinity:正无穷 (如果超出js里面最大的数,将会显示infinity)
  • -Infinity:负无穷 (如果超出js里面最小的数,将会显示-infinity)

数值判断

  • NaN: 表示一个非数值,当无法运算或者运算错误的时候,会得到一个NaN,NaN是number类型,表示一个非数值。
  • NaN与任何值都不想等,包括它本身
  • isNaN: 用来判断是否是一个数字,当返回true的时候说明是NaN,表示的不是一个数字,返回false,说明不是NaN,表示的是一个数字。

示例代码:

var str = "abc";
console.log(isNaN(str)); // true 说明不是一个数字

3.3 String 类型

字面量

字符串的字面量:“abc” 、 ‘abc’ 字符串可以是双引号,也可以是单引号引起来。

不管是双引号,还是单引号,都是成对出现的,假如打印的字符串里有引号怎么办呢?

这里就要活学活用,如果只有一处有引号,就可以用单双引号混合使用:

console.log('我是"帅哥"'); // ==> 我是"帅哥"

假如引号非常多的时候怎么办呢? 用转义字符:“\”:

console.log("我是'帅哥',\"哈哈哈\""); // ==> 我是'帅哥',"哈哈哈"

字符串拼接

拼接字符串使用+号

示例代码:

console.log(11 + 11); // 22
console.log("hello" + " world"); // "hello world"
console.log("100" + "100"); // "100100"
console.log("11" + 11); // "1111"

总结:

  • 两边只要有一个是字符串,那么+就是字符串拼接功能
  • 两边如果都是数字,那么就是算术功能。

字符串长度

length属性用来获取字符串的长度
var str = "abcdefghij";
str.length;// 字符串的长度 10

3.4. boolean 类型

boolean类型只有两个字面量,true和false,区分大小写(True,False不是布尔类型,只是标识符)。

所有类型的值都可以转化成true或者false

NaN、""、undefined、null、alse、0 这6个值可以转换成false,其余的都是true。

3.5 undefined类型与null类型

undefined表示一个声明了没有赋值的变量

var name ;
console.log(name); // undefined

null表示一个空的对象

var name = null;
console.log(typeof name); // Object

如果定义的变量,将来是准备用于保存对象的话,最好将变量初始化为null

var name = null;

undefined 与 null 的关系

undefined == null; // true
undefined === null; // false

实际上,undefiner值是派生自null值的,所以判断相等时为true,但是两种用途是完全不一样的。

4. 简单数据类型转换

如何使用谷歌浏览器,快速的查看数据类型?
  • 字符串的颜色是黑色的
  • 数值类型是蓝色的
  • 布尔类型也是蓝色的
  • undefined和null是灰色的

这个在调试过程中时非常有用的。

4.1 转字符串类型

1、String()函数转换

var num = 123;
console.log(String(num)); // "123"

2、toString() 转换不了undefined 和 null

var num = 123;
console.log(num.toString()); // "123"
console.log(undefined.toString()); // 报错
console.log(null.toString()); // 报错

3、+ "" 加引号

var num = 123;
console.log(num + ""); // "123"

4.2 转数值类型

1、Number

  • 如果转换的是空字符串,返回的是0;
  • 如果是数字字符串,转换后保留原数据;
  • 非数字字符串,转换之后为NaN;
console.log(Number("-123")); // -123
console.log(Number("")); // 0
console.log(Number("123abc")); // NaN

2、parseInt(取整)

  • 小数数字字符串,转换之后,保留整数部分(取整);
  • 数字开头非纯数字字符串,转换之后保留整数部分;
  • 非数字字符串,转换之后为NaN;
console.log(parseInt("123.123")); // 123
console.log(parseInt("123.123abc")); // 123
console.log(parseInt("abc123.123")); // NaN
console.log(parseInt("")); // NaN
console.log(parseInt("abc")); // NaN

3、parseFloat(取数)

  • 数字字符串,转换之后保留原数据;
  • 数字开头的非纯数字字符串,转换之后保留数字部分(包括小数);
  • 非数字字符串转换之后为NaN;
console.log(parseFloat("123.123")); // 123.123
console.log(parseFloat("123.123abc")); // 123.123
console.log(parseFloat("abc123.123")); // NaN
console.log(parseFloat("")); // NaN
console.log(parseFloat("abc")); // NaN

4、参与运算==> "+" or "-0"

var str = "-123";
console.log(+str); // -123
console.log(str-0); // -123

4.3 转布尔类型

布尔类型只有true和false,但是所有类型的值都可以转换成布尔类型

1、能够转换成false的只有6种:

  • ""
  • 0
  • NaN
  • undefined
  • null
  • false

其余的都是true

2、! 转换

var str = "";
// Boolean() 判断这个参数的布尔类型
console.log(Boolean(str)); // false
console.log(!str); // true

5. JS小数运算精度丢失

5.1 JS数字精度丢失的一些典型问题

js在使用小数进行计算的时候,会出现精度丢失的问题。不要用来跟其他的小数做比较。

0.1 + 0.2 != 0.3 //true 0.30000000000000004
// 16位数 和 17位数相等
9999999999999999 == 10000000000000001 // true
9007199254740992 + 1 == 9007199254740992 // true

5.2 JS数字丢失精度的原因

计算机的二进制实现和位数限制有些数无法有限表示。就像一些无理数不能有限表示,如 圆周率 3.1415926...,1.3333... 等。JS 遵循 IEEE 754 规范,采用 双精度存储(double precision) ,占用 64 bit。如图

意义:

  • 1位用来表示符号位
  • 11位用来表示指数
  • 52位表示尾数

浮点数,比如:

0.1 >> 0.0001 1001 1001 1001…(1001无限循环)
0.2 >> 0.0011 0011 0011 0011…(0011无限循环)

此时只能模仿十进制进行四舍五入了,但是二进制只有0和1两个,于是变为0舍1入。这即是计算机中部分浮点数运算时出现误差,丢失精度的根本原因。

大整数的精度丢失和浮点数本质上是一样的,尾数位最大是 52 位,因此 JS 中能精准表示的最大整数是 Math.pow(2, 53),十进制即 9007199254740992。

大于 9007199254740992 的可能会丢失精度:

9007199254740992 >> 10000000000000...000 // 共计 53 个 0
9007199254740992 + 1 >> 10000000000000...001 // 中间 52 个 0
9007199254740992 + 2 >> 10000000000000...010 // 中间 51 个 0

实际上:

9007199254740992 + 1 // 丢失 
9007199254740992 + 2 // 未丢失
9007199254740992 + 3 // 丢失
9007199254740992 + 4 // 未丢失

结果如图:

以上,可以知道看似有穷的数字,在计算机的二进制表示里却是无穷的,由于存储位数限制因此存在“舍去”,精度丢失就发生了。

5.3 JS数字丢失精度的解决方案

对于整数,前端出现问题的几率可能比较低,毕竟很少有业务需要需要用到超大整数,只要运算结果不超过 Math.pow(2, 53) 就不会丢失精度。

对于小数,前端出现问题的几率还是很多的,尤其在一些电商网站涉及到金额等数据。解决方式:把小数放到位整数(乘倍数),再缩小回原来倍数(除倍数)

// 0.1 + 0.2
(0.1*10 + 0.2*10) / 10 == 0.3 // true

6. 运算符

6.1 一元运算符

  • 一元运算符有1个操作数。例如,递增运算符"++",或者递减运算符"--"就是一元运算符。
  • 二元运算符有2个操作数。例如,除法运算符"/"有2个操作数。
  • 三元运算符有3个操作数。例如,条件运算符"?:"具有3个操作数。
递增 "++" 和 递减 "--" 还分为前自增或后自增,前自减或后自减,两种自增自减的运算结果是不一样的;
  • ++num 前自增 --num 前自减 先+1或-1,再返回值
  • num++ 后自增 num-- 后自减 先返回值,再+1或-1

举个例子,看代码:

var num = 5;
console.log(num++); // 5 
console.log(++num); // 7 (因为刚刚num自增了一次,这里打印的话就等于在6的基础上前自增了,在计算机科学中,被称为副效应)
console.log(num--); // 7 (这里是后自减,所以先返回值,返回7,再运算--,此时的num实际是等于6了)
console.log(--num); // 5

6.2 逻辑运算符

  • &&(与运算):只要有一个值为假,结果就是假。找假值 找到假值就返回,如果都是真,返回最后一个
  • ||(或运算):只要有一个值为真,结果就是真。找真值 找到真值就返回,如果都是假,返回最后一个
  • !(非运算):取反

示例代码:

/*细读上面三句话,就能理解为什么会是这个打印结果了*/
console.log(true && true); //true
console.log(false || false); //false
console.log(null && undefined); //null
console.log(null || undefined); //undefined
console.log("abc" && undefined); //undefined
console.log("abc" || undefined); //abc
console.log(null || false || 0 || 1 || null); //1
console.log("abc" && "bcd" && "def"); //def

6.3 运算符的优先级

  • 1、() 优先级最高
  • 2、一元运算符 ++ -- !
  • 3、算数运算符 先* / % 后 + -
  • 4、关系运算符 > >= < <=
  • 5、相等运算符 == != === !==
  • 6、逻辑运算符 先&& 后||

示例代码:

// 第一题 true && true
console.log(((4 >= 6) || ("人" != "狗")) && !(((12 * 2) == 144) && true)); // true
// 第二题 
var num = 10;
// true && true
if(5 == num / 2 && (2 + 2 * num).toString() === "22") {
 console.log(true); // true
}else{
 console.log(false);
}

7. 选择语句

7.1 if..else语句

语法:

只有一个判断条件的时候 if..else:

if(判断条件){ // 当判断条件为true的时候执行代码1,为false的时候执行代码2
 代码1; 
}else{
 代码2;
}

当不止一个判断条件的时候 else用else if 代替:

if(判断条件1){ // 判断条件 1 为 true 的时候执行 代码 1
 代码1; 
}else if(判断条件2){ // 判断条件 2 为 true 的时候执行 代码 2
 代码2; 
}else{ // 两个条件都不满足的时候执行代码 3
 代码3; 
}

思考1:

  • 如果满18,告诉他可以看电影
  • 如果满了16,告诉他可以在家长的陪同下观看
  • 如果不够16,告诉他不准看
var age = 20;
if(age >= 18){
 console.log("没时间解释了,赶紧上车吧"); // 打印这条
}else if(age >= 16){
 console.log("请在家长的陪同下观看");
}else {
 console.log("回家学习吧");
}

思考2:

  • 根据new Date().getDay()获取今天是星期几
  • 由于获取到的是纯数字,现在需要根据这个数字输出"今天是周*"的字符串
var date = new Date(); // 获取当前的时间
var week = date.getDay(); // 获得 0-6 表示周几 0:星期日
if(week == 0){
 console.log("今天是星期天");
}else if(week == 1){
 console.log("今天是星期一");
}else if(week == 2){
 console.log("今天是星期二");
}else if(week == 3){
 console.log("今天是星期三");
}else if(week == 4){
 console.log("今天是星期四");
}else if(week == 5){
 console.log("今天是星期五");
}else if(week == 6){
 console.log("今天是星期六");
}else{
 console.log("你火星的来的吧");
}

7.2 switch..case

语法:

// switch: 开关; case: 案列;
switch(变量){ // 判断变量是否全等于case的值1,或者值2,
 case 值1:
 执行代码1; // 全等于的时候执行代码1
 break; // 然后break;代码跳出switch语句, 不加break,会继续执行下面的代码
 case 值2:
 执行代码2;
 break;
 default:
 执行代码3; // 当都不满足条件的时候,会执行默认里的执行代码3
}

思考:素质教育(把分数变成ABCDE)

// 90-100 : A
// 80-89: B
// 70-79: C
// 60-69: D
// 0-59 : E
// 这里的等级是根据一个范围的分数划定的,用if..else很容易实现,但是switch..case是一个具体的条件,怎么办呢?
// 方法:将分数除以10再用parseInt属性取整
 
var score = 85;
score = parseInt(score/10); // 8
switch (score) {
// score = 10 或者 9 的时候 返回 A
case 10:
case 9:
 console.log("A");
 break;
// score = 8 的时候 返回 B
case 8:
 console.log("B");
 break;
case 7:
 console.log("C");
 break;
case 6:
 console.log("D");
 break;
default:
 console.log("E");
} 

7.3 三元运算符

这个运算符可以用来代替if..else条件判断。但是为什么有这个运算符呢?这里的原因是if..else使用两个代码块,却只有一个会执行,在讲究的程序员看来是一种浪费。所以使用三元运算符,用一条语句就可以完成功能。

语法:

判断语句?表达式1:表达式2; 
根据判断语句返回的布尔值,true的话,返回表达式1,false的话返回表达式2

举个例子,看代码:

var sex = 1;
sex == 1 ? "男":"女"; // 判断sex是否等于1,如果true,返回第一个表达式:"男"

例题:判断两个数的大小

// 用if..else语句解决
// 这里使用了两个代码块,有点浪费
var num1 = 18;
var num2 = 39;
var max;
if(num1>num2){
 max = num1;
}else{
 max = num2;
}
console.log(max);
// 用三元运算符
var num3 = 28;
var num4 = 49;
var max1 = num3>num4? num3:num4;
console.log(max1);

注意(容易出错的地方):

下面这个语句判断如果是会员,费用为2美元,非会员,为10美元。现在设置了非会员,却打印出了2美元,显然出错了。
var isMember = false;
console.log("当前费用" + isMember ? "$2.00" : "$10.00"); // "$2.00"
出错的原因是?号的优先级比+号低,所以实际运行的语句是
// true
console.log("当前费用false" ? "$2.00" : "$10.00"); // "$2.00"

8.循环语句

8.1 while 循环

语法:

  • 1、如果循环条件的结果是true的时候,就会执行循环体
  • 2、如果循环条件的结果是false的时候,结束循环。
// 1. 如果循环条件的结果是true的时候,就会执行循环体
// 2. 如果循环条件的结果是false的时候,结束循环。
while(循环条件){
 循环的代码; // 循环体
 自增或者自减; // 一定不要忘记自增或自减,否则就会死循环
}

例如,求0~100的和:

var num = 0;
var sum = 0;
while(num <= 100){
 sum += num;
 num++;
}
console.log(sum); // 5050

8.2 do..while 循环

语法:

  • do..while循环和while循环非常像,二者经常可以相互替代
  • 但是do..while的特点是不管条件成不成立,都会执行1次。
do{
 循环的代码; // 循环体
 自增或者自减; // 一定不要忘记自增或自减,否则就会死循环
}while(循环条件);

例如,求0~100的和:

var num = 0;
var sum = 0;
do{
 sum += num;
 num++;
}while(num<=100);
console.log(sum); // 5050

8.3 for 循环

写while循环的经常会忘记自增,for循环其实是while循环演化过来的,语法更加的简洁明了,使用非常的广泛。

语法:

  • 初始化表达式
  • 判断表达式
  • 自增表达式
  • 循环体
//主要for循环的表达式之间用的是;号分隔的,千万不要写成,号
for(初始化表达式;判断表达式;自增表达式){
 //循环体
}

例如:求0~100的和:

var sum = 0;
for(var num = 0; num <= 100; num++){
 sum += num;
}
console.log(sum); // 5050

8.4 break 和 continue

break:立即跳出整个循环,即循环结束,开始执行循环后面的内容(直接跳到大括号)continue:立即跳出当前循环,继续下一次循环(跳到i++的地方)

1、continue 示例代码:

for(var i = 1; i <= 10; i++) {
 if(i == 5) {
 continue;
 }
 console.log(i); // 1,2,3,4,6,7,8,9,10
}

2、break 示例代码:

for(var i = 1; i <= 10; i++) {
 if(i == 5) {
 break;
 }
 console.log(i); // 1,2,3,4
}

8.5 循环语句练习

1、计算一个数的位数

当不知道循环次数的时候,用while循环:

var num = 1234567;
//因为不知道循环次数,所以推荐使用while循环
var count = 0; // count记录位数
while(num != 0){ // 循环条件
 num = parseInt(num/10);// 让num缩小10倍
 count++; // ,每缩小10倍就计算一次位数了
}
console.log(count); // 7

2、翻转一个数

var num = 12345678;
//因为不知道循环次数,所以推荐使用while循环
var str = ""; 
while(num != 0){
 str += num%10; // 将每一位取余
 num = parseInt(num/10);//让num缩小10倍
}
// str 是一个字符串,所以 +str将它转回Number类型
console.log(+str); //

3、总结:

  • 循环有很多种,但是以后用得最多的是for循环
  • 当不明确循环次数的时候,可以使用while循环
  • 当无论如何都要执行一次代码的时候,可以使用do..while循环。
  • 循环可以相互替代。

9. 数组

所谓数组,就是将多个元素(通常是同一类型的),按一定顺序排列放到一个集合中,那么这个集合就称之为数组

在javascript中,数组是一个有序的列表,可以在数组中存放任意的数据,并且数组的长度可以动态的调整

9.1 创建数组

1、通过构造函数创建数组:

  • var arr = new Array(); 创建了一个空数组;
  • var arr = new Array('aa','bb','cc'); 创建了一个数组,里面存放了三个字符串
  • var arr = new Array(11,22,33) 创建了一个数组,里面存放了三个数字

2、通过数组子面量创建数组:

  • var arr = []; 创建了一个空数组
  • var arr = [11,22,33]; 创建了一个数组,里面存放了三个数字
  • var arr = ['aa','bb','cc']; 创建了一个数组,里面存放了三个字符串

9.2 数组的下标与长度

数组的下标:

数组是有序的,数组中的每一个元素都对应了一个下标,下标是从0开始的
var arr = ['aa','bb','cc'];
arr[0]; // 下标是0,对应的值是'aa'
arr[2]; // 下标是2,对应的值是'cc'

数组的长度:

跟字符串一样,数组也有一个length的属性,指数组中存放的元素的个数
var arr = ['aa','bb','cc'];
arr.length; // 数组的长度为3

空数组的长度为0

数组的长度与下标的关系:

数组的最大下标 = 数组的长度 - 1

9.3 数组的赋值与取值

数组的取值:

  • 格式:数组名[下标]
  • 功能:获取数组对应下标的那个值,如果下标不存在,返回undefined
var arr = ['red','blue','green'];
arr[0]; // red
arr[2]; // green
arr[3]; // 返回undefined,因为数组最大的下标为2

数组的赋值:

  • 格式:数组名[下标] = 值;
  • 功能:为数组新增值,如果下标有对应的值,会把原来的覆盖,如果下标不存在,会给数组新增一个元素
  • 注意:如果一个数组的最大长度是3,可是却给数组下标为5赋了一个值,则下标为3、4的值为empty(空)
var arr = ["red", "green", "blue"];
arr[0] = "yellow"; // 把red替换成了yellow
arr[3] = "pink"; // 给数组新增加了一个pink的值
arr[5] = "black"; // 数组输出为["red", "green", "blue",empty,empty,"black"]

9.4 数组的遍历

遍历: 对数组的每一个元素都访问一次,叫做遍历

数组遍历的基本语法:

var arr = [1,2,3,4,5,6,7,8,9];
for(var i = 0; i < arr.length; i++){
 console.log(arr[i]); // 1 2 3 4 5 6 7 8 9 
}

数组遍历的逆向遍历语法:

// i= arr.length-1 ==> 表示初始化表达式 从数组最后一位开始遍历
// i>=0 表示判断条件,下标要满足大于等于0
// i--,表示每次遍历 初始值都是自减的
var arr = [1,2,3,4,5,6,7,8,9];
for(var i = arr.length-1; i >= 0; i--){
 console.log(arr[i]); // 9 8 7 6 5 4 3 2 1
}

9.5 数组综合练习

1、求一个数组中的最大值、最小值以及对应的下标

var arr = [298, 1, 3, 4, 6, 2, 23, -88,77,44];
var max = arr[0]; // 随机取数组中的一个值与其他值比较
var maxIndex = 0; // 初始化最大值的下标
var min = arr[0];
var minIndex = 0;
for(var i = 0; i< arr.length; i++){
 if(max < arr[i]){ // 用一开始选择的值,与遍历后的值进行比较
 max = arr[i]; // 当后面的值比初始值大,就将后面的这个值赋值给初始值,再用这个全新的值再v 去与后面的比较
 maxIndex = i; // 比较结束后,此时的索引就是最大值的索引
 }
 if(min > arr[i]){
 min = arr[i];
 minIndex = i;
 }
}
console.log("最大的值是:" + max);
console.log("最大值的下标是:" + maxIndex);
console.log("最小的值是:" + min);
console.log("最小值的下标是:" + minIndex);

2、让数组倒序保存到一个新的数组中

需要了解数组的一个方法 push,在数组的最后面添加

var arr = ["大乔", "小乔", "甄姬", "不知火舞"];
var newArr = [];
for (var i = arr.length - 1; i >= 0; i--) {
 newArr.push(arr[i]);
}
console.log(newArr); // ["不知火舞", "甄姬", "小乔", "大乔"]

3、将字符串数组用"|"或其他符号拼成一个字符串

var arr = ["aa","bb","cc","dd"];
var str = "";
for(var i = 0; i<arr.length; i++){
 if(i == arr.length-1){
 str = str + arr[i]; // 判断一下,如果是最后一个的话就不用加“|”
 }else{
 str = str + arr[i]+"|"; // str初始值是一个空字符串,遍历的时候需要加上前一次的结果
 }
 
}

4、数组去重

  • 定义一个新的数组,分别遍历两个数组,判断两个里的每一项是否相等;
  • 如果发现两个相等,说明是重复的;
  • 当两个不相等的时候,将这个去重数组的当前项push到新数组中;
var arr = [1, 1, 5, 7, 8, 3, 2, 5, 7, 2, 4, 6, 2, 5, 7, 2, 5];
//定义一个新数组
var newArr = [];
//遍历需要去重的数组
for (var i = 0; i < arr.length; i++) {
 //假设不存在
 var flag = true;
 //需要判断arr[i]这个值是否在新数组中存在
 for(var j = 0; j < newArr.length; j++){
 //进行比较即可
 if(arr[i] == newArr[j]){
 //如果发现了相等的数,说明存在
 flag = false;
 }
 }
 if(flag){
 //如果假设成立,说明不存在
 newArr.push(arr[i]);
 }
}
console.log(newArr);

10. 冒泡排序

10.1 冒泡排序的思路

一个有8位元素的数组,让它的第一位与后面每一位进行比较,前面一位小于后面的时候,位置不变,前面的大于后面的交换位置,就这样一共要比七趟(最后一趟不要比,就剩一位,就是最小的);

实现原理如下图:

10.2 按性能等级冒泡排序分3个等级

1、冒泡排序 60分:

var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
var tang = 0;
var ci = 0;
for (var i = 0; i < arr.length - 1; i++) { // 外层for循环,循环的是比较的趟数,因为只要比较8趟 所以i判断的条件为length-1
 tang++;
 for (var j = 0; j < arr.length - 1; j++) { // 内层for循环,循环的是比较的次数,每趟比较8次
 ci++;
 if (arr[j] > arr[j + 1]) { // 判断比较的两个数,如果前面的大于后面的一位,交换位置
 var temp = arr[j];
 arr[j] = arr[j + 1];
 arr[j + 1] = temp;
 }
 }
}
console.log("趟数:" + tang); // 8趟
console.log("次数:" + ci); // 64次
console.log(arr);
}
  • 外层for循环,循环的是比较的趟数,因为只要比较8趟(数组长度为9) 所以i判断的条件为length-1;
  • 内层for循环,循环的是比较的次数,每趟比较8次,其实这里次数多比较了,因为第一趟已经找到一个最大值了,第二趟就不需要比8次了 应该比7次,这里先不管,下面会进行优化;
  • 判断比较的两个数,如果前面的大于后面的一位,交换位置。

测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title></title>
</head>
<body>
 <span id="demo"></span><br/>
 <button id="stb">从小到大</button>
 <button id="bts">从大到小</button>
 <span id="show">
</span>
 <script>
 var demo = document.getElementById("demo");
 var show = document.getElementById("show");
 var bts = document.getElementById("bts");
 var stb = document.getElementById("stb");
 var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
 demo.innerHTML = arr;
 bts.onclick = function() {
 bubbleSort(function(a, b) {
 return b - a;
 });
 }
 stb.onclick = function() {
 bubbleSort(function(a, b) {
 return a - b;
 });
 }
 function bubbleSort(fn) {
 var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
 var strArr = [];
 show.innerHTML = "";
 strArr.push("<br/>");
 var inner = 0;
 var outer = 0;
 for (var i = 0; i < arr.length - 1; i++) {
 strArr.push("第" + (i + 1) + "趟");
 for (var j = 0; j < arr.length - 1; j++) {
 if (fn(arr[j], arr[j + 1]) > 0) {
 var tmp = arr[j];
 arr[j] = arr[j + 1];
 arr[j + 1] = tmp;
 }
 inner++;
 }
 strArr.push(arr.toString());
 strArr.push("共" + j + "次" + "<br/>");
 outer++;
 }
 strArr.push("外循环" + outer + "次");
 strArr.push("内循环" + inner + "次");
 show.innerHTML = strArr.join(" ");
 }
 </script>
</body>
</html>

每趟都比较8次?明显是多余了,下面进行优化

2、冒泡排序80分:

var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
var tang = 0;
var ci = 0;
for (var i = 0; i < arr.length - 1; i++) {
 tang++;
 for (var j = 0; j < arr.length - 1 - i; j++) { // 第二趟只比了7次 依次递减
 ci++;
 if (arr[j] > arr[j + 1]) {
 var temp = arr[j];
 arr[j] = arr[j + 1];
 arr[j + 1] = temp;
 }
 }
}
console.log("趟数:" + tang); // 8趟
console.log("次数:" + ci); // 36次
console.log(arr);

i 是从下标0开始的,第一趟的时候i=0,比了8次,第二趟i=1,只需要比7次,第三趟i=2,只需要比6次...依次类推,所以 比的次数应该就是arr.length - 1 -i;

测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title></title>
</head>
<body>
 <span id="demo"></span><br/>
 <button id="stb">从小到大</button>
 <button id="bts">从大到小</button>
 <span id="show">
</span>
 <script>
 var demo = document.getElementById("demo");
 var show = document.getElementById("show");
 var bts = document.getElementById("bts");
 var stb = document.getElementById("stb");
 var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
 demo.innerHTML = arr;
 bts.onclick = function() {
 bubbleSort(function(a, b) {
 return b - a;
 });
 }
 stb.onclick = function() {
 bubbleSort(function(a, b) {
 return a - b;
 });
 }
 function bubbleSort(fn) {
 var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
 var strArr = [];
 show.innerHTML = "";
 strArr.push("<br/>");
 var inner = 0;
 var outer = 0;
 for (var i = 0; i < arr.length - 1; i++) {
 strArr.push("第" + (i + 1) + "趟");
 for (var j = 0; j < arr.length - 1 - i; j++) {
 if (fn(arr[j], arr[j + 1]) > 0) {
 var tmp = arr[j];
 arr[j] = arr[j + 1];
 arr[j + 1] = tmp;
 }
 inner++;
 }
 strArr.push(arr.toString());
 strArr.push("共" + j + "次" + "<br/>");
 outer++;
 }
 strArr.push("外循环" + outer + "次");
 strArr.push("内循环" + inner + "次");
 show.innerHTML = strArr.join(" ");
 }
 </script>
</body>
</html>

还有什么可以优化的吗? 假如8个数在第3趟的时候就排好了,还需要继续排吗?

3、冒泡排序100分:

假设成立法(3步):

  • 假设成立
  • 想办法推翻假设
  • 如果推翻不了,说明假设成立
var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
var tang = 0;
var ci = 0;
for (var i = 0; i < arr.length - 1; i++) {
 var flag = true; // 假设每一次进来都排好了
 tang++;
 for (var j = 0; j < arr.length - 1 - i; j++) {
 ci++;
 if (arr[j] > arr[j + 1]) {
 flag = false; // 如果两位比较还满足前面的比后面的大的时候,说明假设不成立
 var temp = arr[j];
 arr[j] = arr[j + 1];
 arr[j + 1] = temp;
 }
 }
 if (flag == true) { // 最后判断一下,如果假设推翻不了,就停止运行。
 break;
 }
}
console.log("趟数:" + tang); // 4 趟
console.log("次数:" + ci); // 26 次
console.log(arr);

当顺序已经排好后,就不用再去执行趟数了;

测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title></title>
</head>
<body>
 <span id="demo"></span><br/>
 <button id="stb">从小到大</button>
 <button id="bts">从大到小</button>
 <span id="show">
</span>
 <script>
 var demo = document.getElementById("demo");
 var show = document.getElementById("show");
 var bts = document.getElementById("bts");
 var stb = document.getElementById("stb");
 var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
 demo.innerHTML = arr;
 bts.onclick = function() {
 bubbleSort(function(a, b) {
 return b - a;
 });
 }
 stb.onclick = function() {
 bubbleSort(function(a, b) {
 return a - b;
 });
 }
 function bubbleSort(fn) {
 var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
 var strArr = [];
 show.innerHTML = "";
 strArr.push("<br/>");
 var inner = 0;
 var outer = 0;
 for (var i = 0; i < arr.length - 1; i++) {
 var sorted = true;
 strArr.push("第" + (i + 1) + "趟");
 for (var j = 0; j < arr.length - 1 - i; j++) {
 if (fn(arr[j], arr[j + 1]) > 0) {
 var tmp = arr[j];
 arr[j] = arr[j + 1];
 arr[j + 1] = tmp;
 sorted = false;
 }
 inner++;
 }
 strArr.push(arr.toString());
 strArr.push("共" + j + "次" + "<br/>");
 outer++;
 if (sorted) {
 break;
 }
 }
 strArr.push("外循环" + outer + "次");
 strArr.push("内循环" + inner + "次");
 show.innerHTML = strArr.join(" ");
 }
 </script>
</body>
</html>

第三趟已经排好了,为什么还要排第四趟呢? 原因很简单,因为第三趟的时候js是不知道你已经排好的,只有第四趟的时候,js再进行换位比较的时候,发现位置都不需要换了,说明排好了。

如果觉得不错可以关注微信公众号:编程成长记