前端开发进阶 JavaScript

假设你已经拥有至少一门编程语言的基础了(建议 C 语言)。

JavaScript简介

JavaScript (简称 js )是一种轻量级的脚本语言(不具备开发操作系统的能力),而是只用来编写控制其他大型程序的“脚本”。

js 是一种嵌入式语言,既不是完全的编译型语言,也不是传统意义上的解释型语言,而是介于两者之间的语言。它的执行机制混合了编译和解释的特点。它运行的单位是行,一行一行地执行,一般每一行就是一个语句。

为什么学习js

  • 操作浏览器的能力
  • 广泛的使用领域
  • 易学性

变量声明赋值

  • 语句:一般每一行就是一条语句,以分号结尾。
  • 标识符:就是变量名,由字母、美元符号($)、下划线(_)、数字组成,其中数字不能开头。(保留字不能做标识符)

声明赋值格式:

1
2
3
4
// var : variable
var num = 10;
var $a_1sdfg = "iwen";
var zs = "张三";

控制台

为了打印变量,可以采用浏览器中的控制台(console),将 js 代码嵌入 html 文件中(使用<script></script> 标签),再通过浏览器打开,F12进入控制台即可。

那么,不妨先往控制台输出一下“Hello world!”吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>

<body>
<script>
console.log("Hello world!")
</script>
</body>

</html>

变量提升

js 引擎工作的方式是变量提升,即运行时把所有变量的声明都提到最前面,赋值留在后面,因此下面的代码不会报错,而是输出“undefined”:

1
2
console.log(num);
var num = 10;

引入文件

我们写的 js 代码需要像 css 一样被引入到 html 文件中,有如下方法:

嵌入到 HTML 文件中

1
2
3
4
<script>
var age = 20;
console.log(age);
</script>

引入本地独立 js 文件(常用)

1
2
3
<body>
<script src="./hello.js"></script>
</body>

引入网络来源文件

1
2
3
<body>
<script src="http://code.jquery.com/jquery1.2.1.min.js"></script>
</body>

注释

源码中注释是不被引擎所解释的,它的作用是对代码进行解释,js 有两种注释的写法:一种是单行注释,用“//”起头;另一种是多行注释,放在“/* */”之间。

1
2
3
4
5
6
// 这是单行注释
/*
这是
多行
注释
*/

嵌入在 HTML 文件中的注释:

1
<!-- 注释 -->

输出方式

  • 弹窗输出:在浏览器中弹出一个对话框,然后把要输出的内容展示出来,alert 都是把要输出的内容首先转换为字符串然后再输出的。
1
alert("要输出的内容");
  • 写入页面输出:
1
document.write("我是输出到页面");
  • 控制台输出:
1
console.log("控制台输出");

数据类型

ES5版本 js 中有六种数据类型:数值,字符串,布尔值,null,对象,undefined。

其中可以分类为原始数据类型(基本数据类型):数值、布尔值、字符串和合成类型(复合类型/引用类型):null、对象(object)、undefined。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 数值类型
var age = 20;
// 字符串类型:被双引号或单引号包裹的值
var name = "iwne";
var name2 = "电子科技大学";
// 布尔类型
var flag = true;
var flags = false;
// 对象
var user = {
name:"张三",// 这里用逗号隔开
age:20,
learn:true;
}
// null 和 undefined 一般看成两个特殊值, 一般 null 代表对象没有,undefined 代表数值没有。
var hello = null;
var world = undefined;

判断基本数据类型:使用 typeof 运算符

1
2
3
4
5
6
7
8
9
var age = 20;
var name = "iwen";
var flag = true;
var user = {};
console.log(typeof age) // number
console.log(typeof name) // string
console.log(typeof flag) //boolean
console.log(typeof user) // object
console.log(typeof []) // object

运算符

算数运算符

包括加减乘除,取模,自增自减,和 C 基本相同,注意 i++++i的区别(前者的值是之前的i,后者的值是之前的i+1,但是执行后i都加 1 )。

1
2
3
4
5
6
7
8
9
var num1 = 1000;
var num2 = 100;
console.log(num1 + num2); // 1100
console.log(num1 - num2); // 900
console.log(num1 / num2); // 10,除法不整除默认按照浮点数来算,类似 Python3
console.log(num1 % num2); // 0
var num3 = 20;
console.log(++num3); // 21
console.log(--num3); // 20

赋值运算符

把等号(=)右边的赋值给左边的,和 C 相同,可以使用+=,-=,*=,/=,%=

比较运算符

常见的是>,<,>=,<=,这里注意 js 存在严格相等运算符(===)和相等运算符(==),还有不相等运算符(!=)和严格不相等运算符(!==),区别如下(类似 php ):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var num1 = 10;
var num2 = 10;
console.log(num1 == num2); // true
console.log(num1 === num2); // true

var num3 = 10;
var num4 = "10";
console.log(num3 == num4); // true
// “==”比较时,js会把字符串先转换为数据
console.log(num3 === num4); // false
// “==”只比较值,“===”比较值和类型,类似php

console.log(num3 != num4) // false
console.log(num3 !== num4) //true

布尔运算符

即或(||),且(&&),非(!)运算符,其中注意非运算符会把如下值都变为 true:

1
2
3
4
5
6
!undefined
!null
!false
!0
!NaN
!"" //空字符串

三元运算符

即 C 的 判断?第二句:第三句,判断为真执行第二句,否则执行第三句。

条件语句

if...else if... else...结构。

1
2
3
4
5
6
7
if(day === 0){
...
}else if(day === 1){
...
}else{

}

还有 switch-case-default语句也可使用。

1
2
3
4
5
6
7
8
9
10
switch(day){
case 0:
...
break;
case 1:
...
break;
default:
...
}

循环语句

包括 for 循环, while 循环和 do-while 循环,可以使用 break,continue。和 C 相同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for(var i = 1;i<=100;i++){
...
}

var i = 100;
while(i>=0){
...
i--;
}

var count = 1;
do {
console.log("Count is:", count);
count++;
} while (count <= 5);

字符串

从这里开始基本就是 js 的独特之处啦~

js 中字符串就是由0个或多个排在一起的字符,外层加上双引号或单引号。

如果字符串中想使用双引号/单引号,可以使用“  ”转义,也可以外层引号与字符串内引号不同类型。

字符串默认一行显示,需要换行的话使用“  ”

1
2
3
var str1 = ''我要输出\'\'';
var str2 = "我要\
换行 ";

length 属性

length 属性返回字符串的长度。

1
2
var s = "1234123";
s.length; // 7

charAt 方法

charAt 方法返回指定位置的字符,参数从 0 开始编号。

1
2
var str = "itxiaobaibai";
console.log(str.charAt(4)); // a

concat 方法

concat 方法用来连接两个字符串,返回一个新字符串,不改变原字符串。可接受多个参数。

如果参数不是字符串,函数会把输入先转化为字符串再连接。

另一种字符串相连接的方法是直接使用“+”。

1
2
3
4
5
6
var str1 = "Hello";
var str2 = "World";
var num = 100;
var result = str1.concat(str2,"!",num);
console.log(result); // HelloWorld!100
console.log(str1 + str2); // HelloWorld

substring 与 substr 方法

substring 方法用于从原字符串中取出子字符串并返回,不改变原字符串。它的第一个参数表示子字符串的开始位置,第二个位置表示结束位置(返回结果不含该位置),如果省略第二个参数,则子字符串一直到原字符串的结束(如果第一个参数大于第二个参数,自动交换,如果有负数参数,自动变为0)。

substr 方法和 substring 基本相同,区别为第二个参数是子字符串的长度。

1
2
3
var name = "itxiaobai";
console.log(name.substring(2,8)); // xiaoba
console.log(name.substr(2,6)); // xiaoba

indexOf 方法

indexOf 方法用于确定一个字符串在另一个字符串中第一次出现的位置,返回结果是匹配开始的位置。如果返回 -1,就表示不匹配。

该方法也可以接收第二个参数,表示从当前位置向后匹配。

1
2
var hello = "helloworld";
console.log(hello.indexOf("e")); // 1

trim 方法

trim 方法用于去除字符串两端的空格,返回一个新字符串,不改变原字符串。

所去除的不仅是空格,包括空白字符:制表符(“ ,“ ),换行符(“ ”),回车符(“ ”)。

ES6扩展方法,trimEnd()trimStart(),仅去掉一端。

1
2
var str = "   123   ";
console.log(str.trim()); // 123

split 方法

split 方法按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组。传入空字符串则把每个字符都分割,如果不传参数返回只有原字符串的数组。可以传入第二个参数:返回数组的最大长度。

1
2
var name = "it|sxt|it";
console.log(name.split("|")); // ['it', 'sxt', 'it']

数组

数组(Array)是按次序排列的一组值。每个值的位置都有编号(从 0 开始),整个数组用方括号表示。

1
var arr = ['sxt', 'it'];

除了在定义时赋值,也可以先定义后赋值。

1
2
3
var arr = [];
arr[0] = 'sxt';
arr[1] = 'it';

任何类型的数据,都可以放入数组。

1
var arr = [100, [1,2,3], false];

如果数组的元素还是数组,就形成了多维数组。

1
2
3
var a = [[1,2], [3,4]];
a[0][1] // 2
a[1][1] // 4

length 属性

返回数组的长度。

1
2
var a = [[1,2], [3,4]];
console.log(a.length); // 2

数组的遍历可以采用 for 循环,for-each 的方法也是存在的,但是要注意这里的循环变量只是代表索引而不是值。

1
2
3
for(var i in a){
console.log(a[i]);
}

isArray 静态方法

Array.isArray 方法返回一个布尔值,表示参数是否为数组,可以弥补 typeof 运算符的不足。

1
2
var arr = [10, 20, 30];
console.log(Array.isArray(a)); // true

push, pop 方法

push 方法在数组的末端添加一个或多个元素,并返回添加新元素后数组的长度。

1
2
var arr = [];
console.log(arr.push(1)); // 1

pop 方法用来删除数组的最后一个元素,并返回该元素。

1
2
var arr = [1,2,3];
console.log(arr.pop()); // 3

shift, unshift 方法

shift 方法用来删除数组的第一个元素,并返回该元素。

1
2
var arr = [1,2,3];
console.log(arr.pop()); // 1

unshift 方法在数组的头部添加一个或多个元素,并返回添加新元素后数组的长度。

1
2
3
var arr = [200];
arr.unshift(100,1200);
console.log(arr); // [100, 1200, 200]

join 方法

join 方法以指定参数作为分割符,将所有数组成员连接为一个字符串返回。如果不提供参数,默认用逗号分割。

1
2
var a = [1,2,3,4];
a.join("|"); // 1|2|3|4

concat 方法

cancat 方法用于多个数组的合并。它将新数组的成员,添加到原数组的后部,然后返回一个新数组,原数组不变。

该函数也可以接收一般变量,添加到数组的后部。

1
['hello'].concat(['world']); // ['hello', 'world']

reverse 方法

reverse 方法用于颠倒排列数组的元素,返回改变后的数组。(注意:会改变原数组)。

1
2
var arr = [1,2,3,4,5];
arr.reverse(); // [5,4,3,2,1]

indexOf 方法

indexOf 方法返回给定元素在数组中第一次出现的位置,不存在返回 -1。

该方法也可以接收第二个参数,表示从当前位置向后匹配。

1
2
var arr = [1,2,3,4,5];
console.log(arr.indexOf(30)); // -1

函数

函数是一段可以反复调用的代码块。

funcion 命令:function 命令声明的代码区块,就是一个函数。function 命令后面是函数名,函数名后面是一对圆括号,里面是传入函数的参数。函数体放在大括号里面。

JavaScript 引擎将函数名视同变量名,所以采用 function 命令声明函数时,整个函数会像变量声明一样,被提升到代码头部。

函数参数放在函数名后面的括号里。

使用return返回结果。

1
2
3
function print(s){
console.log(s);
}

对象

对象(object)是一组键值对(key-value)的集合,是一种无序的复合数据集合。

1
2
3
4
var user = {
name:"it";
age:13;
};

“值”可以是任何数据类型,如果是函数,就把这个属性成为“方法”,它可以像函数那样调用。

1
2
3
4
5
var user = {
getName: function (name){
return name;
}
};

Math 对象

Math 是 js 的原生对象,提供各种数学功能,包括:

  • abs:返回绝对值。
  • max,min:返回最大值/最小值。
  • floor,ceil:向下/向上取整。
  • random:返回0到1之间的一个伪随机数,可能等于0,但是一定小于1。

Date 对象

Date 是 js 原生的时间库。它以1970年1月1日 00:00:00 作为时间的零点,可以表示的时间范围是前后各1亿天(单位为毫秒)。

下面是一些常用方法:

  • now:返回当前时间距离时间零点的毫秒数,相当于 Unix 时间戳(距离零点的总秒数)乘上1000。
  • getTime:返回距离零点的毫秒数。
  • getDate:返回是每个月的几号。
  • getDay:返回星期几,星期日为0,星期一为1,以此类推。
  • getYear:返回距离1900的年数。
  • getFullYear:返回四位的年份。
  • getMonth:返回月份(0代表1月,11代表12月)。
  • getHours:返回小时(0~23)。
  • getMilliseconds:返回毫秒(0~999)。
  • getMinutes:返回分钟(0~59)。
  • getSeconds:返回秒(0~59)。
1
2
3
var d = new Date('January 6, 2022');
d.getDate(); // 6
d.getMonth(); // 0

DOM

DOM是 js 操作网页的接口,全程为“文档对象模型(Document Object Model)”,作用是将网页转为一个 js 模型,从而可以用脚本进行各种操作(比如对元素增删改查)。

浏览器会根据 DOM 模型,将结构化文档 HTML 解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。所有的节点和最终的树状结构,都有规范的对外接口。

DOM 只是一个接口规范,可以用各种语言实现,严格来说 DOM 不是 js 语法中的一部分,但是 DOM 操作是 js 最常见的任务,离开了 DOM,js 就无法控制网页。另一方面,js 也是最常用于 DOM 操作的语言。

节点

DOM 最小组成单位叫做节点(node)。文档的属性结构(DOM树),就是由各种不同类型的节点组成。

节点的类型有七种:

  • Document:整个文档树的顶层节点
  • DocumentType:doctype 标签
  • Element:网页的各种 HTML 标签
  • Attribute:网页元素的属性
  • Text:标签之间或标签包含的文本
  • Comment:注释
  • DocumentFragment:文档的片段

节点树

一个文档的所有节点(html,body,p,div等),按照所在的层级,可以抽象成一种树状结构。这种树状结构就是 DOM 树。它有一个顶层节点,下一层都是顶层节点的子节点,然后子节点又有自己的子节点,就这样衍生出一个金字塔结构,倒过来像一棵树。

浏览器原生提供 document 节点,代表整个文档

1
console.log(document); // 整个 HTML 文件

除了根节点,其他节点都有子节点,父节点,同级节点的关系。

Node.nodeType 属性

不同节点的 nodeType 属性值和对应的常量如下:

  • 文档节点(document):9,对应常量Node.DOCUMENT_NODE
  • 元素节点(element):1,对应常量Node.ELEMENT_NODE
  • 属性节点(attr):2,对应常量Node.ATTRIBUTE_NODE
  • 文本节点(text):3,对应常量Node.TEXT_NODE
  • 文档片段节点(DocumentFragment):11,对应常量Node.DOCUMENT_FRAGMENT_NODE
1
2
3
if(document.nodeType === 9){
console.log("顶层节点");
}

document对象

document.getElementsByTagName()

document.getElementsByTagName方法搜索 HTML 标签名,返回符合条件的元素。它的返回值是一个类似数组对象(HTMLCollection实例),可以实时反应 HTML 文档的变化。如果没有任何匹配的元素,就返回一个空集。

如果传入“*”,就可以返回文档中所有 HTML 元素。

1
2
var paras = document.getElementsByTagName('p');
var paras = document.getElementsByTagName('*');
1
2
3
4
5
6
7
8
<body>
<div>Hello1</div>
<div>Hello2</div>
<script>
var div1 = document.getElementByTagName('div')[0];
div1.innerHTML = "Hello world";//更改标签内元素
</script>
</body>

document.getElementsByClassName()

读取类名,和上一个同理。

1
2
3
4
5
6
<body>
<p class="text">Hello</p>
<script>
var text = document.getElementsByClassName("text")[0];
</script>
</body>

document.getElementsByName()

读取表单中的 name,同理,不常用。

1
2
3
4
5
6
<body>
<form action="" name="123"></form>
<script>
var forms = document.getElementsByName('123');
</script>
</body>

document.getElementById()

读取 id 属性,同理,非常常用,注意这里的 element 不是复数。

1
var elem = document.getElementById('para1');

document.querySelector()

接受一个 CSS 选择器作为参数,返回匹配该选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回 null。

1
var el1 = document.querySelector(".nav");

document.querySelectAll()

和上面类似,这里返回的不是第一个,而是一个数组。

1
var el1 = document.querySelector(".nav")[0];

document.createElement()

用来生成元素节点,并返回该节点。

1
var newDiv = document.createElement('div');

document.createTextNode()

用来生成附带文本的节点(Text实例),并返回该节点,参数是文本节点的内容。

1
2
3
var newDiv = document.createElement('div');
var newContent = document.createTextNode('hello');
newDiv.appendChild(newContent);// 文本信息加入到标签

document.createAttribute()

生成一个新的属性节点(Attr实例),并返回它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<body>
<div id="container"></div>
<script>
var text = document.createElement("p");
var content = document.createTextNode("我是文本");
var id = document.createAttribute("id");
id.value = "root";
text.appendChild(content);
text.setAttributeNode(id);
console.log(text);
var container = document.getElementById("container");
container.appendChild(text);
</script>
</body>