目录
JavaScript基本使用语法
JavaScript的书写方式
与CSS相同,JavaScript的书写方式有三种,分别是行内式、内嵌式和分离式
- 行内式例如:
<input type="button" value="按钮" onclick="alert('提示文字')" >
- 内嵌式例如:
<body>
</body>
<script>
alert('提示文字');
</script>
内嵌式一般放在<body>
元素后
- 分离式例如:
在HTML中使用script:src
引入JS文件
<script src="./分离式.js"></script>
在JS文件中写JavaScript的代码
alert("提示文字");
接下来的内容均基于分离式编写,在HTML中只引入文件,没有特殊要求不展示HTML代码
老生常谈
在JavaScript中,可以使用console.log()
向网页控制台调试器打印内容(称日志),使用其打印Hello World
,代码如下:
// 打印Hello World
console.log('Hello World');
查看浏览器控制台可以看到打印的内容,如下:
需要注意,JavaScript中的语句规范是末尾带分号,如果没有带分号,JavaScript解释器会帮助添加分号,但是不推荐
在JavaScript中,字符串可以使用双引号""
,也可以使用单引号''
,所以上面的代码也等同于下面:
console.log("Hello World");
JavaScript的注释
JavaScript中的注释分为单行注释和多行注释
- 单行注释
// 单行注释
- 多行注释(不可嵌套)
/*
多行注释
*/
JavaScript数据类型与变量
定义JavaScript变量
在JavaScript中声明变量不需要指定变量的类型,一共有两种方式定义变量:
- 使用
var
定义变量(不推荐)
var a = 1;
- 使用
let
定义变量(推荐)
let a = 1;
如果既没有使用var
也没有使用let
,则定义的变量可以认定为全局变量,例如a = 1;
语句中的a
可以认为是全局变量
JavaScript的基本数据类型
变量 | 解释 |
String | 字符串类型(一串文本):字符串的值必须用引号(单双均可,必须成对)括起来。可以使用 |
Number | 数字类型:无需引号。JS 中不区分整数和浮点数, 统一都使用number表示数字类型来表示. |
Boolean | 布尔类型(真 / 假): |
Undefined | 未定义类型 |
null | 空值 |
// 基本数据类型
let num = 1; // number类型
let str = 'Hello World' + 'Hello World'; // string类型
console.log(str.length); // 获取字符串长度
let bool = true; // boolean类型
let n = null; // null类型
let u;// undefined类型
输出结果:
22
- 模版字符串
在ES6之后,推出了一种特殊的字符串,使用``
包裹,称为模版字符串,该字符串有以下几个特点:
- 字符串内容可以换行
- 字符串中可以嵌入变量和表达式,使用
${}
包裹
例如下面的代码:
// 模版字符串
let str = `模版字符串
可以换行`;
console.log(str);
// 嵌入变量
let username = '小明';
let age = 18;
console.log(`我叫${username},今年${age}岁。`);
JavaScript变量的特点
在JavaScript中,变量都是动态弱类型变量
- 弱类型变量和强类型变量:
强类型变量:不同类型之间的转换需要进行显示强制转换
弱类型变量:不同类型之间的转换不需要显示强制类型转换
// 定义数值类型的变量
let num = 1;
console.log(num);
// 定义字符串类型的变量
let str = 'Hello World';
console.log(str);
// 将数值类型的变量转换为字符串类型
str = num;
console.log(str);
- 动态类型变量与静态类型变量:
动态类型变量:在运行时可以随意改变变量的类型
静态类型变量:在运行前确定变量的类型,运行时不可以修改变量的类型
// 定义数值类型的变量
let num = 1;
console.log(typeof(num));
// 定义字符串类型的变量
let str = 'Hello World';
console.log(typeof(str));
// 将数值类型的变量转换为字符串类型
str = num;
console.log(typeof(str));
在JavaScript中可以使用typeof()
函数查看参数的数据类型
JavaScript中的特殊数字值
Infinity:无穷大
-Infinity:负无穷大
NaN:非数值类型
// JavaScript中的特殊数值
console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log("0" / 0); // NaN
JavaScript中的强制类型转换
一般情况下,为了更好地存储用户输入的数据,变量一般都是字符串类型,而此时如果是需要与数值类型进行数学运算,就需要用到强制类型转换
string
转换number
将字符串转换成number
可以使用下面两种方式:
- 使用
Number()
强制转换:这种方法如果在字符串中有无法转换的字符,就会转换失败返回NaN
- 使用
parseInt()
函数转换:这种方法会从第一个字符开始识别,遇到非数值字符就停止,并且因为是转换成整数,所以包括遇到小数点也停止 - 使用
parseFloat()
函数转换:这种方法同parseInt()
,但是不会忽略小数点 - 在需要转换的字符串前加上
+
:最快捷的方法,可以在表达式中使用,例如let sum = +age + 1;
任意类型转换成string
将任意类型转换成string
有下面的几种方式:
- 使用
String()
强制转换 - 使用
toString()
函数转换:这个函数是一个对象函数,调用对象是需要转换的字符串,参数表示进制类型,例如下面的代码:
let num = 10;
num.toString(2); // 1010
JavaScript运算符
==
与===
JavaScript中的运算符与Java中的运算符基本一致,额外需要注意的是==
与===
在JavaScript中,==
用于判断两个变量内容是否一致,而===
用于判断两个变量的类型和内容是否都一致
// == 和 ===
let num = 1;
let str = '1';
console.log(num == str); // true
console.log(num === str); // false
同样可以推出!=
与!==
JavaScript运算符优先级
优先级 | 运算符类型 | 结合性 | 运算符 |
19 | 分组 | n/a(不相关) |
|
18 | 成员访问 | 从左到右 |
|
带计算的成员访问 | 从左到右 |
| |
| n/a |
| |
函数调用 | 从左到右 |
| |
可选链(Optional Chaining) | 从左到右 |
| |
17 | new(无参数列表) | 从右到左 |
|
16 | 后置递增 | n/a |
|
后置递减 |
| ||
15 | 逻辑非 | 从右到左 |
|
按位非 |
| ||
一元加法 |
| ||
一元减法 |
| ||
前置递增 |
| ||
前置递减 |
| ||
typeof |
| ||
void |
| ||
delete |
| ||
await |
| ||
14 | 幂 | 从右到左 |
|
13 | 乘法 | 从左到右 |
|
除法 |
| ||
取余 |
| ||
12 | 加法 | 从左到右 |
|
减法 |
| ||
11 | 按位左移 | 从左到右 |
|
按位右移 |
| ||
无符号右移 |
| ||
10 | 小于 | 从左到右 |
|
小于等于 |
| ||
大于 |
| ||
大于等于 |
| ||
in |
| ||
instanceof |
| ||
9 | 相等 | 从左到右 |
|
不相等 |
| ||
一致/严格相等 |
| ||
不一致/严格不相等 |
| ||
8 | 按位与 | 从左到右 |
|
7 | 按位异或 | 从左到右 |
|
6 | 按位或 | 从左到右 |
|
5 | 逻辑与 | 从左到右 |
|
4 | 逻辑或 | 从左到右 |
|
空值合并 | 从左到右 |
| |
3 | 三元运算符 | 从右到左 |
|
2 | 赋值 | 从右到左 |
|
| |||
| |||
| |||
| |||
| |||
| |||
| |||
| |||
| |||
| |||
| |||
| |||
| |||
| |||
| |||
1 | 逗号/序列 | 从左到右 |
|
JavaScript分支与循环语句
使用方式与Java中的基本相同
JavaScript数组
创建数组
在JavaScript中,一共有两种数组创建的方式:
- 使用
new
关键字创建
// 使用new关键字创建数组
let arr = new Array(1, 2, 3);
- 使用字面量创建数组(通过元素个数推导创建)
// 使用字面量创建数组
let arr1 = [1, 2, 3];
JavaScript的数组不要求数组中的每一个元素类型相同,例如下面的数组:
// 不同类型的元素
let arr2 = [1, 'Hello World', true, null, undefined];
数组遍历
与Java基本一致,但是在JavaScript中,如果直接打印数组名,则打印直接显示的并不是地址,而是整个数组的内容和数组的属性
// 数组遍历
let arr = [1, 2, 3];
console.log(arr);
但是如果将数组名赋值为其他字面量,则数组会因此改变数据类型为字面量的数据类型
let arr = [1, 2, 3];
console.log(typeof(arr));
arr = "Hello World";
console.log(arr);
console.log(typeof(arr));
在JavaScript中,数组属于一个对象object类型
需要注意,JavaScript中如果越界访问是不会抛出越界访问异常的,相反,会打印对应下标的值为undefined
数组元素新增
在JavaScript中允许数组在运行时插入元素,一共有三种插入方式:
- 增加数组的
length
属性:扩大后的length
比原来的length
多出来的部分如果没有给定值则默认为undefined
let arr = [1, 2, 3];
// 1. 修改length属性
arr.length = 5;
console.log(arr); // [1, 2, 3, empty * 2]
console.log(arr[4]); // undefined
- 通过下标直接指定某一个位置的值:指定的下标大于原来的下标时,会将指定的值放置在指定的下标位置,此时数组的
length
属性也会改变,并且指定的下标与原来最大的下标中间的部分默认为undefined
let arr = [1, 2, 3];
// 2. 通过下标直接赋值
arr[5] = 5;
console.log(arr[5]); // 5
console.log(arr[4]); // undefined
- 使用
push()
方法插入:该方法传递一个参数,该参数即为需要插入的元素,默认在数组的尾部最后一个元素的下一个位置插入,并且会改变length
属性
let arr = [1, 2, 3];
// 3. 使用push方法
arr.push(8);
console.log(arr[6]); // 8
console.log(arr.length); // 7
数组元素的删除
在JavaScript中,删除数组也有三种方式
- 减小
length
属性
let arr = [1, 2, 3, 4, 5];
// 1. 修改length属性
arr.length = 3;
console.log(arr); // [1, 2, 3]
console.log(arr.length); // 3
- 使用
pop()
方法:该方法没有参数,默认删除最后一个元素,并且会改变length
属性
// 2. 使用pop方法
arr.pop();
console.log(arr); // [1, 2]
console.log(arr.length); // 2
- 使用
splice()
方法,该方法含有两个参数,第一个参数是删除的第一个元素的下标,第二个参数是删除元素的个数(最小为1,即删除第一个参数对应的元素)
// 3. 使用splice方法
arr.splice(0, 1);
console.log(arr); // [2]
console.log(arr.length); // 1
JavaScript函数
函数定义
在JavaScript中,定义一个函数需要使用下面的格式
function 函数名(形参列表) {
函数体
返回语句(可选)
}
在JavaScript中,因为函数定义不需要显示写返回值,所以是否有返回值或者返回值类型是什么取决于返回语句的有无以及返回的数据类型,例如下面的两个函数
// JavaScript函数
// 带返回值函数
function add(a, b) {
return a + b;
}
// 调用函数,获取返回值
let sum = add(1, 2);
// 不带返回值函数
function print() {
console.log('Hello World');
}
// 调用函数
print();
JavaScript函数形参与实参可以不匹配
在JavaScript中,函数实参的个数可以不需要与形参列表个数完全匹配(实参少于形参或实参多于形参)
- 实参少于形参:此时多的形参在函数内将被认为
undefined
,此时如果有算术运算并返回,则会返回NaN
- 实参多于形参:此时多的实参将会被函数形参列表忽视
// 实参多于形参
function add(a, b) {
return a + b;
}
let sum1 = add(1, 2, 3);
console.log(sum1); // 3
// 实参少于形参
function add(a, b) {
return a + b;
}
let sum2 = add(1);
console.log(sum2); // NaN
尽管JavaScript允许形参和实参个数不匹配,但是在实际开发中仍然建议将二者严格匹配
JavaScript函数表达式
在JavaScript中,可以使用一个变量接收函数,再通过该变量调用函数,此时函数名可以省略
// 函数表达式
let ret = function(a, b) {
return a + b;
};
let sum = ret(1, 2);
console.log(sum); // 3
// 不省略函数名
let ret1 = function add(a, b) {
return a + b;
};
let sum2 = ret1(1, 2);
console.log(sum2); // 3
作用域与作用域链
作用域
在JavaScript中,每一个变量拥有自己所在的作用域,而不会冲突于子域中的重定义变量,例如定义在函数外部的局部变量不会与函数内部作用域中定义的同名局部变量冲突
// 作用域
let a = 1;
function test() {
let a = 2;
console.log(a);
}
console.log(a); // 1
test(); // 2
作用域链
在JavaScript中,允许在函数内部继续定义一个新的函数
如果函数内部使用的变量在函数内部并不存在,则会依次向外作用域查询直到找到同名变量,称为作用域链
// 函数内部作用域存在需要使用的变量,直接使用当前作用域中的变量
let a = 1;
function test() {
let a = 2;
function test1() {
let a = 3;
console.log(a);
}
test1(); // 3
}
console.log(a); // 1
test(); // 3
// 函数内部作用域不存在需要使用的变量,依次向外作用域寻找
let a1 = 1;
function test() {
function test1() {
console.log(a1);
}
test1(); // 1
}
console.log(a1); // 1
test(); // 1
JavaScript对象
定义对象
在JavaScript中,一共有4种方式定义对象
- 直接使用
let 对象名={属性}
:每一个属性都是一个键值对,每一个属性由逗号分隔。如果不写属性部分不写任何内容则代表创建一个空对象。在属性中,如果需要定义方法,则该方法为匿名函数,需要注意这个函数不需要使用function
关键字
// 1. 使用字面量
let people = {
name: 'Jack',
age: 18,
speak: function() {
console.log('Hello World');
},
eat: function() {
console.log('I am eating');
}
};
- 使用
let 对象名=new Object()
创建对象:创建后的对象默认不具备属性,可以通过对象名依次增加属性。如果需要增加方法,则可以使用函数(匿名函数)表达式
// 2. 使用new Object()
let people1 = new Object();
people1.name = 'Jack';
people1.age = 18;
people1.speak = function() {
console.log('Hello World');
};
people1.eat = function() {
console.log('I am eating');
};
- 使用构造函数创建对象:该构造函数实际上是一个类名为对象抽象模版,该函数参数即为创建的对象具有的属性,函数体内部使用
this
区分形参和属性。在创建对象时,实参作为对象的属性值。此时如果需要创建方法,同样使用函数(匿名函数)表达式
// 3. 使用构造函数
function People(name, age) {
this.name = name;
this.age = age;
this.speak = function() {
console.log('Hello World');
};
this.eat = function() {
console.log('I am eating');
};
}
let people2 = new People('Jack', 18);
- 使用
class
关键字创建对象抽象模版:在类内使用constructor
代替第三种方式中的构造函数,如果需要创建方法,此时直接使用函数名+形参列表的方式即可,但是JavaScript中的属性不存在修饰符限制
// 4. 使用class关键字
class People3 {
constructor(name, age) {
this.name = name;
this.age = age;
}
speak() {
console.log('Hello World');
}
eat() {
console.log('I am eating');
}
}
let people3 = new People3('Jack', 18);
访问对象
JavaScript中访问属性有两种方式
- 访问对象具有的属性名
- 使用
['属性名']
访问
class People {
constructor(name, age) {
this.name = name;
this.age = age;
}
speak() {
console.log('Hello World');
}
eat() {
console.log('I am eating');
}
}
let people = new People('Jack', 18);
console.log(people.name);
console.log(people['age']);
people.speak();
people.eat();
static
关键字
在JavaScript ES6标准后,因为多了class
关键字,所以JavaScript也支持了静态属性和静态方法,需要注意的是,在JavaScript中,静态属性和方法不可以被对象调用
class People {
constructor(name, age) {
this.name = name;
this.age = age;
}
static type = 'Human';
speak() {
console.log('Hello World');
}
eat() {
console.log('I am eating');
}
static walk() {
console.log("I'm walking");
}
}
let people = new People('Jack', 18);
// 正常属性和方法调用
console.log(people.name);
console.log(people['age']);
people.speak();
people.eat();
// 静态属性和方法调用
console.log(People.type);
People.walk();
继承
在JavaScript ES6后,JavaScript也支持继承,继承方式类似于Java
// JavaScript继承
class People {
constructor(name, age) {
this.name = name;
this.age = age;
}
static type = 'Human';
speak() {
console.log('Hello World');
}
eat() {
console.log('I am eating');
}
static walk() {
console.log("I'm walking");
}
}
class Student extends People {
// 学生新增属性grade
constructor(name, age, grade) {
super(name, age); // 使用super关键字调用父类的构造函数
this.grade = grade;
}
study() {
console.log('I am studying');
}
}
let student = new Student('Jack', 18, 3);
// 子类访问父类的属性
console.log(student.name);
console.log(student.age);
// 子类新增属性
console.log(student.grade);
// 子类调用父类的方法
student.speak();
student.eat();
student.study();
// 子类调用父类的静态属性和静态方法
console.log(Student.type);
Student.walk();