JaveScript介绍
之前学习的HTML和CSS做的是页面的静态效果
如果要实现页面上一些功能和交换效果,需要js
- HTML--页面结构
- CSS--页面样式
- JS--页面行为(动态)
什么是JS
- 是一种编程语言
- 唯一运行在浏览器上的语言
JS组成
js由三部分组成:ECMAscript,DOM,BOM
- ECMAscript:js语法的语言规范
- DOM:文档对象模型,用来操作页面上的标签
- BOM:浏览器对象模型,用来操作浏览器的部分功能
JS能做什么
- 网站/Web开发
- 命令行工具
- 桌面程序
- App
- 服务端开发
- 控制硬件,物联网
- 游戏开发
JS书写位置
js同css一样有三种书写方式:行内式,内嵌式,外链式
行内式
<body>
<input type="button" value="按钮" onclick="alert('Howlle word!')">
<!--onclick为css样式,alert为js代码-->
</body>
内嵌式
<script>
alert('Hollow word!!');
</script>
外链式
<script src="01_JS_书写位置.js">
//里面不能写代码
</script>
输入输出方法
输入
弹出框
作用:用于在浏览器上弹出提示框(无取消按钮)
语法:alert(" "); / alert(' ');
<script>
alert('Hollow word!');
//or
alert("Hollow word!");
//最好用单引号
</script>
控制台打印日志
作用:浏览器开发者工具中输出信息
语法:console.log(' ');
console.log('Howlle woer!');
输出
提示框
作用:弹出提示框(有取消按钮)
语法:confirm(' ');
confirm('提示内容');
输入框
作用:提示用户输入
语法:prompt('内容');
prompt('请输入数字');
注:以上输入输出均属于DOM类
变量和常量
定义变量
语法:var 变量名称 = 数据; 或 let 变量名称 = 数据;
//test01
let num1=1;
console.log(num1);
//test02
let num2=prompt('请输入数字');
console.log(num2);
除test02输入方式外,其他同C++
变量命名规则和规范
规则(法律):
- 不能以数字开头,由字母,数字,下划线,$符组成
- 不能是关键字和保留字
- 区分大小写
- 使用let定义的变量名不允许重复,使用var定义的变量名允许重复
规范(道德):
- 变量名尽量有意义
- 首字母小写,后面单词首字母大写,例:userName
关键字和保留字
关键字:具有特殊意义的单词,例:var
保留字:未来可能出现的关键字,js保留了下来
定义常量
语法:const 变量名称 = 数据;
注:常量在定义时,必须赋值
数据类型
数据类型分为简单数据类型和复杂数据类型
简单数据类型:
- Number
- String
- Boolean
- null
- undefined
- Bigint--新增
- Symbol--新增
复杂数据类型:
- Object
Number类型
所有数值都属于Number类,包括整数和浮点数
数值字面量:
- 用字面形式来表示数值类
- 例:110 22
特殊数值(属Number类):
- NaN:not a number,非数字
- isNaN():is not a number,判断是否为非数字
let num1=1;
console.log(num1);
let num2=2;
console.log(num2*'a');//输出为NaN,非数字
let num3=3;
console.log(isNaN(num3));
输出结果:
注: 所有输出结果均为Number类
String类
字符串字面量:
- 字面形式来代表字符串数据
- 使用单引号或双引号包裹字符串
- 例:'sdau'或"10000"
注:同'111'这类用单引号或双引号包裹的数字属于String类
let str1='test01';
let str2='1111';
console.log(str1);
console.log(isNaN(str2));
运行结果:
注:Number类与String类在控制台中显示颜色不一样
输出单引号或双引号:
使用转义字符\
let str3='\'test02\'';
Boolean类
布尔字面量:true和false
true为1,false为0
Null和Undefined类
null:赋值了,值为空
undefined:定义了,未赋值
let a;
console.log(a);
//输出为undefined
let b=null;
console.log(b);
//输出为null
数据类型转换
问题引入:
let num1 = prompt('输入第一个数:');
let num2 = prompt('输入第二个数:');
let sum = num1 + num2;
console.log(sum);
如上代码,输入1和2
输出却为12
因为通过prompt获得的数据为字符串型
所有需要数据类型转换
转换数值类
三种方法:Number(),parseInt(),parseFloat()
1.Number()
可以把任意值转化为数值类
注:如果字符串中有一个不是数值的字符,返回NaN
let test01 = '100';
console.log(test01);
let test02 = Number(test01);
console.log(test02);
let test03 = Number('5a');
console.log(test03)
let test04 = Number(true);
console.log(test04);
let test05 = Number(null);
console.log(test05);
let test06 = Number(undefined);
console.log(test05);
运行结果:
2.parseInt()
将字符串转为整数
不保留小数点后
从前往后解析数字,一直到非数字为止,返回非数字前的数值
let test11=parseInt('110a11');
console.log(test11);
let test12=parseInt('a111');
console.log(test12);
let test13=parseInt('10.2');
console.log(test13);
运行结果:
3. parseFloat()
将字符串转为浮点数
与parseInt()相似,但会保留第一个小数点后的数
let test21=parseFloat('11.2');
console.log(test21);
let test22=parseFloat('11.2a11');
console.log(test22);
let test23=parseFloat('16.5.3.4');
console.log(test23);
运行结果:
4.其他方式
可以利用取正,取负及减法运算使字符串转为数值类
let test='5555';
console.log(+test); //55555
console.log(-test); //-5555
console.log(test-0); //5555
转换字符串类
1.toString()
将数值类和布尔类转为字符串类
let test01=1000;
let test02=true;
console.log(test01.toString());
console.log(test02.toString());
注:undefined类和null类不可以用这个方式转为字符串类
2.String()
可以把任意值转化为字符串类,包括undefined类和null类
let test11=1000;
console.log(String(test11));
let test12=true;
console.log(String(test12));
let test13=null;
console.log(String(test13));
let test14=undefined;
console.log(String(test14));
运行结果:
3.隐式转换法
例:num + ‘ ’
当+两边一个操作符为字符串类,一个为其他类型时
会先把其他类型转为字符串类,再进行拼接
let test=true;
console.log(test+'')
转换布尔类
利用Boolean()来施行转换
可以把任意值转化为布尔类
转换规则:
- 0,‘空字符串’,null,undefined,NaN,false转为false
- 其他转为true
算术运算符
大部分同C++
注:==与===
- ==会进行隐式类型转换,会先把字符串类转为数值类
- ===不会进行隐式类型转换,不仅比较数值,还比较类型
- !=与!==同理
- 建议用3=
数组补充
1.JS中的数值可以随数组长度动态调整
let arr = [1, 2, 3];
arr[3] = 4;
console.log(arr[3]);
let arr1 = [];
arr1[0] = 1;
console.log(arr1[0]);
2.数组可以直接打印,不用通过循环
let arr2=[1,2,3,4];
console.log(arr2);
运行结果:
3.不用每一项都赋值
未赋值则为空
let arr3=[];
arr3[0]=1;
arr3[100]=2;
console.log(arr3);
运行结果:
4.获取数组中元素个数
语法:数组名.length
console.log(arr3.length);
5.数组构造函数
可以使用构造函数创建数组
let arr4=new Array();
//等同于let arr4=[];
注意:
如果只有一个数据,不要使用
只给一个数字,会认为设置数组长度
let arr5 = new Array(100);
console.log(arr5);//输出[empty*100]
函数
函数的定义与调用
函数定义
语法:
function 函数名(参数){
函数体
}
函数调用
语法:函数名(参数)
补充
函数也是一种数据类型
可以把函数作为值传递给另一个函数
function test01(){
return 0;
}
function test02(num,test01){
test01();
return 0;
}
以参数形式,传入另一个函数,并在其内被调用的函数,称为 回调函数
函数的返回值
语法:
function 函数名(参数){
函数体
return 返回值;
}
可以通过变量来接收返回值
let 变量名 = 函数名(参数);
默认返回值为:undefined
arguments使用
arguments可以解决要求任意个数的数字和问题
注:arguments只能在函数内部使用,不需要声明
function test01(){
console.log(arguments);
}
test01(1);
test01(1,2,3);
test01(1,2,3,4,5);
arguments具有数组的特征,但不是数组,称为伪数组
arguments根据传进来的参数,来组成伪数组
匿名函数
匿名函数不能单独存在
function(参数){
函数体
}
//报错,不能单独存在
示例:
要通过函数表达式做声明
let test01 = function () {
return 0;
}
作用域与预解析
作用域
作用域
变量或者函数能够使用的范围 称为 作用域
作用域分为 全局作用域 和 局部作用域
全局作用域:
在<script>标签内和JS文件中,书写范围即全局作用域
全局作用域中定义的变量称为全局变量
局部作用域:
创建函数的时候,函数内部为局部作用域
局部作用域中定义的变量称局部变量
使用范围:
全局变量可以在程序的任意位置使用
局部变量只能在其局部作用域内使用,即函数内部
作用域链
作用域是可以嵌套的
在嵌套的作用域中,当函数访问变量,会先在当前作用域找到变量
如若在当前作用域未找到变量,则会到上一级作用域寻找,如此循环
这样的作用域嵌套称为 作用域链
预解析
如下代码:
var a = 20;
test01();
function test01() {
console.log(a);
var a = 60;
}
运行结果既不是20,也不是60,而是undefined
原因是JS的预解析过程
预解析:
JS在执行代码时,首先进行预解析
将var和function的声明提升到最前端(只提升声明,没有赋值)
其他顺序不变
然后再从上往下执行代码
以上代码预解析后为:
var a;
function teat01() {
var a;
console.log(a);
a = 60;
}
a = 20;
test01();
var和function的声明提升称为变量提升和函数提升
函数声明和函数表达式的区别
//函数声明
function test01() {
console.log('01');
}
//函数表达式
var test02 = function () {
console.log('02');
}
test01();
test02();
如上代码,可正常运行,二者没有区别
区别:
test01();
test02();
//函数声明
function test01() {
console.log('01');
}
//函数表达式
var test02 = function () {
console.log('02');
}
如果调用放到前面test02会报错
原因:预解析
预解析结果:
function tset01() {
console.log('01');
}
var test02;
test01();
test02();
test02 = function () {
console.log('02');
}
所以test02会报错
函数优先
如果函数和变量重名,提升时函数会覆盖变量
如果函数重名,后定义覆盖先定义
块级作用域
代码块:一个大括号引起来的范围就是一个代码块
let与const会在代码块中形成作用域,为块级作用域
{
var a = 10;
}
console.log(a);
{
let b = 20;
}
console.log(b);
如上,b的值无法输出
因为let再大括号内形成块级作用域,b为局部变量
let/var/const区别
- const定义常量,必须给初值
- var没有块级作用域,而let/const由块级作用域
- let/const有变量提升,但是声明和赋值之间的代码不能访问(称为暂时性死区)
对象
创建对象
object构造函数
object是一个函数,需要结合new调用
可以通过object来创建对象
语法:
let 对象名 = new Object();
对象字面量
语法:
let 对象名 = { };
对象属性
赋值方法
方法1:
对象名 . 属性名 = 属性值;
注:如果打印对象中没有的属性,返回undefined
方法2:
let 对象名 = {
属性名 : 属性值,
属性名 : 属性值 //赋值
};
补充
当属姓名不是合法标识符时,可以用[ ] //遍历对象时也用
示例:stu [ ' 000 ' ] = ' xxxx ';
console.log ( stu [ ' 000 ' ] ) ;
对象行为
语法:
对象名.行为名 = function () {
函数体
}
或
let 对象名 = {
行为名 :function() {
函数体
}
};
this
在行为里面,可以通过this来调用对象其他属性
this代表当前行为的所属对象
示例:
let person = {
name: aa,
work: function () {
console.log(this.name);
}
};
遍历和删除对象属性
遍历
使用一个新的循环语法:for···in
作用:将对象的属性名逐个赋值给变量
示例:
let test01 = {
x1: 1,
x2: 2,
x3: 3
}
for (let key in test01) {
console.log(key);
console.log(test01[key]);
}
//test01的属性名逐个赋值给key
运行结果:
删除
删除对象属性,使用关键字delete
语法:
delete 属性;
delete test01.x1;
内置对象
内置对象,就是JS中本身自带的一些功能对象,提供了一些属性和方法
部分内置对象:
- Math
- Date
- Array
- String
- Number
- Boolean
Math
Math.PI | 属性,返回圆周率 |
Math.floor()/Math.ceil() | 向下/上取整(传参) |
Math.random() | 生成随机数[0,1) |
Math.round() | 四舍五入(传参) |
Math.abs() | 取绝对值(传参) |
Math.max()/Math.min() | 最大/小值(传参) |
Math.pow()/Math.sqrt() | 求指数次幂/平方根(传参) |
Math.sin()/Math.cos() | 正弦/余弦(传参) |
示例:
返回10~30的随机数
let a;
a = Math.random();
let b;
b = a * 20 + 10;//区间由[0,1)变为[10,30)
console.log(b);
Date
Date是一个构造函数,需要用new来调用,返回日期对象
let now = new Date();
//获取当前时间
console.log(now);
运行结果:
Sun Jul 21 2024 11:49:01 GMT+0800 (中国标准时间)
创建特定日期:
let now = new Date(2024,7,21);
let now = new Date('2024-7-21');
获取时间的毫秒形式
let now01 = Date.now();
console.log(now01);
获取日期指定部分
date.getSeconds() | 返回0-59 |
date.getMinutes() | 返回0-59 |
date.getHours() | 返回0-23 |
date.getDay() | 返回星期几 |
date.getDate() | 返回当前月的第几天 |
date.getMonth() | 返回月份 |
示例:
计算时间差:
function dateDiff(start, end) {
let diff = end - start;
//日期对象在进行数学计算时,会自行转换为毫秒值
diff /= 1000;//转换为秒值
let day = Math.floor(diff / 60 / 60 / 24);
let hour = Math.floor(diff / 60 / 60 % 24);
let minute = Math.floor(diff / 60 % 60);
let second = Math.floor(diff % 60);
return {
d_day: day,
d_hour: hour,
d_minute: minute,
d_second: second
}
}
let start = new Date(2024, 6, 21, 16, 00, 00);//月份从0开始,6代表7月
let end = new Date();
console.log(start);
console.log(end);
let diff = dateDiff(start, end);
console.log(diff);
Array
创建数组对象
let arr=new Array();
let arr=[];
常用属性和行为
(arr为数组名)
arr.length | 获取数组长度 |
arr.push()/arr.pop() | 添加/取出最后的元素(传参) |
arr.shift()/arr.unshift() | 取出/添加最前面的元素(传参) |
arr.join() | 传递一个参数,作为分隔符(传参) |
arr.reverse() | 翻转数组 |
arr.indexOf() | 返回数组中元素位置(第一个匹配元素), 从前往后找,-1为没找到(传参) |
arr.lastIndexOf() | 返回数组中元素位置(第一个匹配元素), 从后往前找,-1为没找到(传参) |
arr.concat() | 传入一个数组,拼接两个数组(传参) |
arr.splice() | 删除或替换元素(传参) |
arr.sort() | 排序,根据ASCII码顺序 |
基本类型包装对象
除了null和undefined以外,所有基本类型都有其对应包装对象
- String
- Number
- Boolean
可以作为构造函数调用,会创建对应的对象
以String为例:
let str = new String('wdf?');
console.log(str);
String对象
字符串的不可变性
修改字符串后,会生成新字符串赋值,原字符串不会删除,且占内存
因为字符不可变,对字符串操作会返回新字符串,所以需要接受
例:
let s = '123';
s = s.concat('456');
常用成员
(str为字符串名)
str.charAt()/str[ ] | 获取指定位置字符(传参) |
str.concat() | 拼接字符串(传参),等效于+ |
str.indexOf() | 返回数组中元素位置(第一个匹配元素), 从前往后找,-1为没找到(传参) |
str.lastIndexOf() | 返回数组中元素位置(第一个匹配元素), 从后往前找,-1为没找到(传参) |
str.trim() | 清除前后空格 |