JavaScript基础
1. JavaScript简介
- JavaScript,就是我们通常所说的JS,是一种嵌入到HTML页面中的脚本语言,由浏览器一边解释一边执行。
- “HTML是网页的结构,CSS是网页的外观,而JavaScript是页面的行为。”
2. JavaScript的特点
- 动态改变页面内容
HTML页面是静态的,一旦编写,内容是无法改变的。JavaScript可以弥补这个不足,可以将内容动态地显示在网页中。
- 动态改变网页的外观
JavaScript通过修改网页元素的CSS样式,达到动态地改变网页的外观。
- 验证表单数据
我们常见的在各大网站中的注册中的验证功能,就是JavaScript实现的。
- 响应事件
JavaScript是基于事件的语言。例如点击一个按钮弹出一个对话框,就是鼠标点击触发的事件。
对于JavaScript的理解,就一句话:如果没有使用JavaScript,网页就是静态的,唯一的功能就是给用户浏览。加入了JavaScript,网页变得绚丽多彩起来。
3. JavaScript入门基础
3.1 Javascript基本使用
3.1.1 JavaScript在HTML的引用方式
(1)页头引入(head标签内);
<script>
alert('沙漠骆驼')
</script>
(2)页中引入(body标签内);
(3)元素事件中引入(标签属性中引入);
<input type="button" value="唐伯虎" οnclick="alert('秋香姐')">
(4)引入外部JS文件 (script之间不可以再写东西了);
<script src="my.js"></script>
3.1.2 注释
- 单行注释 ctrl + /
- 多行注释 shift + alt + a
多行注释 vscode中修改多行注释的快捷键: ctrl + shift + /
3.1.3 输入输出语句
-
prompt 输入框
prompt('请输入您的年龄');
-
alert 弹出警示框 输出的 展示给用户的
alert('计算的结果是')
-
console 控制台输出 给程序员测试用的
console.log('我是程序员能看到的')
3.2 Javascript数据结构
JavaScript的数据结构包括:标识符、关键字、常量、变量等。
1. 标识符
-
标识符,说白了,就是一个名字。在JavaScript中,变量和函数等都需要定义一个名字,这个名字就可以称为“标识符”。
-
命名规范:
(1)第一个字符必须是字母、下划线(_)或美元符号这3种其中之一,其后的字符可以是字母、数字或下划线、美元符号;
(2)变量名不能包含空格、加号、减号等符号;
(3)标识符不能和JavaScript中用于其他目的的关键字同名;
2. 关键字
JavaScript关键字是指在JavaScript语言中有特定含义,成为JavaScript语法中一部分的那些字。
3. 常量
常量主要用于为程序提供固定和精确的值,包括数值和字符串,如数字、逻辑值真(true)、逻辑值假(false)等都是常量。
4. 变量
变量,顾名思义,就是指在程序运行过程中,其值是可以改变的。
-
声明和赋值
-
声明了一个age变量
var age;
-
声明了一个age变量
age = 18;
-
输出结果
console.log(age);
-
变量的初始化
let myname = 'sheep'; console.log(myname);
-
-
声明变量的特殊情况
-
只声明不赋值 结果是 undefined 未定义的
let sex; console.log(sex);
-
不声明不赋值 直接使用某个变量会报错
console.log(tel);
-
不声明直接赋值使用
qq = 110; console.log(qq);
-
5. 声明变量 let
(1) let介绍
ES6引入了let,用let声明变量,解决了JavaScript没有块级作用域的问题(注:ES3的catch分句会产生块作用域)。
(2) 作用域
作用域简单的来说,就是一套寻找变量的规则,用于确定在何处以及如何查找变量
-
当一个块或函数嵌套在另一个函数时,就发生了作用域嵌套=。如图所示,就有三个嵌套作用域:
-
全局作用域,其中有一个标识符:foo(整个绿色区域)
-
foo创建的函数作用域,其中有三个标识符:a,bar和b(整个黄色区域)
-
bar创建的函数作用域,其中有一个标识符:c(蓝色区域)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wpUYoWWr-1668609019253)(https://gitee.com/colohh/image_bed/raw/master/img/%E5%B5%8C%E5%A5%97%E4%BD%9C%E7%94%A8%E5%9F%9F.png)]
-
-
如何在嵌套作用域中寻找变量呢:引擎从当前作用域开始查找变量,如果找不到,就会向上一级继续查找。当抵达最外层全局作用域时,无论找到还是没有找到,查找过程中都会停止。
(3) let 特点
-
作用域只在他所在的代码块
for(let i = 0 ; i<5 ; i++) { let i = 'cht'; console.log(i); // cht *5 } // console.log(i); //Error:i is not defined
-
let 不允许在相同的作用域内,重复声明同一个变量
-
let 声明不使用会报错
-
不存在变量提升
ES6明确规定,如果区块中存在let/const命令,这个区块用这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用的变量,就会报错
-
外层作用域不能访问内层变量;内层变量可访问外层变量。
-
不影响作用域链
{ let school = 'china'; function fn(){ console.log(school); } fn();// china }
3.3 JavaScript数据类型
js是动态语言,变量的数据类型是可以变化的。只有程序在运行过程中,根据等号右边的值来确定
3.3.1 基本数据类型:
(1)数字型(Number型):如整型84,浮点型3.14;
let num = 10; // num 数字型
let PI = 3.14 // PI 数字型
-
-
八进制 0 ~ 7 我们程序里面数字前面加0 表示八进制
let num1 = 010; console.log(num1); // 010 八进制 转换为 10进制 就是 8
-
-
-
十六进制 0 ~ 9 a ~ f #ffffff 数字的前面加 0x 表示十六进制
var num3 = 0x9; console.log(num3);
-
-
- 数字型的最大值
console.log(Number.MAX_VALUE);
- 数字型的最大值
-
- 数字型的最小值
console.log(Number.MIN_VALUE);
- 数字型的最小值
-
- 无穷大
console.log(Number.MAX_VALUE * 2); // Infinity 无穷大
- 无穷大
-
- 无穷小
console.log(-Number.MAX_VALUE * 2); // -Infinity 无穷大
- 无穷小
-
- 非数字
console.log('pink老师' - 100); // NaN
- 非数字
isNaN() 这个方法用来判断非数字 并且返回一个值 如果是数字返回的是 false 如果不是数字返回的是true
console.log(isNaN(12)); // false
console.log(isNaN('pink老师')); // true
(2)字符串型(String型):如"pink";
字符串的拼接:
-
- 检测获取字符串的长度 变量名.length
let str = 'my name is andy';
console.log(str.length);//15
-
- 字符串的拼接 +
console.log('hello'+' '+'world');
console.log('618'+'大促');
注意:字符串+其他类型 最后结果也一定是字符串型
console.log('12'+12);
例: 输出我今年age岁(”引引加加“)
console.log('我今年' + age + '岁')
变量不能写到字符串里面,是通过和字符串相连的方式实现的
(3)布尔型(Boolean型):true或fasle;
let flag = true;
let flag1 = false;
ture / false 参与加减法运算当 1 / 0来看
3.3.2 特殊数据类型:
(1)空值(null型);
let space = null;
console.log(space + 'pink'); // nullpink
console.log(space + 1); // 1
(2)未定义值(undefined型);
let str;
console.log(str);
let variable = undefined;
console.log(variable + 'pink'); // undefinedpink
console.log(variable + 1); // NaN undefined 和数字相加 最后的结果是 NaN
(3)转义字符;
\n 换行 ; \b 空格 ;杠’ 和杠" ; \b 空格;
3.3.3 获取变量数据类型 typeof 变量名
let num = 10;
console.log(typeof num);//number
3.3.4 数据类型转换
-
转换成字符型
-
利用 变量.toString()
let num = 10; let str =num.toString(); console.log(str); console.log(typeof str);
-
利用 String(变量)
console.log(String(num));
-
!!利用 + 拼接字符串的方法实现转换效果 隐式转换
let str1 =' '+num; console.log(str1); console.log(typeof str1);
-
-
转换成数字型
-
将string类型转换成整型 parseInt(变量)
console.log(parseInt('24.75'));//3 取整 console.log(parseInt('120px'));//120 会自动去掉非整型部分 console.log(parseInt('rem120px'));//NaN 读到第一个字符非数字型就不继续读了
-
将string类型转换成浮点型 parseFloat(变量)
语法同parselnt
-
利用 Number(变量)
let str2 = '123' console.log(Number(str2)); console.log(Number('152'));
-
利用了算术运算 - * / 隐式转换
console.log('12' - 0);//12 console.log('123' - '120');//3
-
-
转换为布尔型 Boolean(函数)
“ " ”、“0”、“NaN”、“underfined”、“null”转换后值为false,其余都为true
console.log(Boolean(null));//false console.log(Boolean('我很好'));//ture
3.4 运算符
也叫操作符
JavaScript的运算符按运算符类型可以分为以下5种:
(1)算术运算符
“+”-“*”/"
- 浮点数在算数运算中会有误差,不能判断浮点数是否相等
-
表达式和返回值
- 表达式是由数字、运算符、变量等组成的式子 1+1
(2)递增和递减运算符
-
a. 前置递增(++num)
-
b.后置递增(num++)先返回原值,再自加
-
例题:
let a = 10;
++a;
let b = ++a + 2;
console.log(b); // 14
let c = 10;
c++;
letlet d = c++ + 2;
console.log(d); // 13
let e = 10;
let f = e++ + ++e;
console.log(f); // 22
(3)比较运算符;
- 是两个数据进行比较时所使用的运算符,比较运算后,会返回一个布尔值(ture / false)作为比较运算的结果。
(4)逻辑运算符;
逻辑与 && 、逻辑或 || 、逻辑非 !
用来进行布尔值运算的运算符,其返回值也是布尔值。后面开发中经常用于多个条件的判断
-
短路运算(逻辑中断)
原理:当有多个表达式(值)时,左边的表达式可以确定结果时,就不再继续运算右边表达式的值;
- 逻辑与(从左往右数有错误的就输出错误的,全对就输出最后一个)
- 语法:表达式1 && 表达式2
- 若表达式1为真,则返回表达式2
- 若表达式1为假,则返回表达式1
例:
console.log(123 && 456);// 456
console.log(0 && 456);// 0
-
逻辑或(从左往右数有正确的就输出正确的,全错就输出最后一个)
- 语法:表达式1 || 表达式2
- 若表达式1为真,则返回表达式1
- 若表达式1为假,则返回表达式2
例:
console.log(123 || 456);// 123
console.log(0 || 456);// 456
console.log(123 || 456 ||789);// 789
// 经例: let num = 0; console.log(123 || num++); //程序读到123为真后逻辑中断返回123,num++不执行,此时num为0 console.log(num);// 0
- 逻辑与(从左往右数有错误的就输出错误的,全对就输出最后一个)
(5)赋值运算符
用来把数据赋值给变量的运算符
- 自加 (自减、乘、除同理)
num = num + 1; // num++
num = num + 2;// num +=2
(6)运算符优先级
熟练掌握优先级并计算以下案例:
3.5 流程控制分支结构
流程控制就是来控制代码按照什么结构顺序来执行
顺序结构/分支结构/循环结构
3.5.1 顺序流程控制
- 按照代码先后顺序,依次执行
3.5.2 分支流程控制if语句
-
分支结构
-
从上到下的代码中,根据不同条件,执行不同路径代码(多选一),从而得到不同的结果。
-
提供了两种分支结构语句
-
(1)if 语句
-
双分支语句(if else语句)
-
语法结构(2选1)
if (条件表达式){ //执行语句1; } else { //执行语句2; }
-
执行思路:若 if 里的表达式结果为 ture ,则执行语句1,反之则执行语句2;( else 可以不写)
-
-
多分支语句( if else if 语句)
-
语法结构(多选1)
if(条件表达式1){ //语句1; } else if(条件表达式2){ //语句2; } else if(条件表达式3){ //语句3; }else { //最后的语句; }
-
执行思路:若条件表达式 1 的结果为 ture ,则执行语句1,否则继续往下判断直到找到结果为ture的表达式,若全不满足,则输出最后的语句。
-
-
补充:三元表达式
-
由三元运算符组成的式子我们称为三元表达式
-
语法结构
- 条件表达式 ? 表达式1 :表达式2
-
执行思路
-
如果条件表达式结果为真,则返回表达式1的值;
-
如果条件表达式结果为假,则返回表达式2的值。
let num = 10; let result = num > 5 ? '是的' : '不是的';// 是的 //等价于 if(num > 5){ result ='是的'; }else{ result ='不是的'; }
-
-
(2)switch 语句
switch 语句也是多分支语句,它用于基于不同的条件来执行不同的代码。当要针对变量设置一系列的特定值的选项时,就可以使用switch。
-
语法结构
switch(表达式){ case value1:// 值1 执行语句1; break; case value2:// 值2 执行语句2; break; ... ... ... default: 执行最后的语句; }
-
执行思路:利用表达式的值 和 case 后面的选项值 相匹配,如果匹配上,就执行该case里面的语句;如果都没匹配上,那么执行 default里面的语句
-
一般情况下,可以相互转换
-
switch…case 通常处理case为比较确定值的情况,而 if…else…语句更加灵活,常用于判断范围(大于或等于某个范围)
-
switch进行条件判断后直接执行到程序的条件语句,效率更高。而 if…else 语句有几种条件,就得判断几次
-
分枝少时用 if…else…if ;分枝多用 switch…case
3.5.3 循环流程控制
(1)for循环
-
for重复执行某些代码,通常和计数有关
-
语法结构
for (初始化变量;条件表达式;操作表达式){ //循环体 }
-
初始化变量:就是用 var 声明的一个普通的变量,通常作为计数器使用
-
条件表达式:用来决定每一次循环是否继续执行,就是终止的条件
-
操作表达式:每次循环最后执行的代码 通常用于我们计数器变量进行更新(递增或者递减)
-
代码体验 重复打印100句 你好
for(var i = 1;i <= 100;i++){ alert('你好') }
(2)双重for循环
-
语法结构
for (外层的初始化变量;外层的条件表达式;外层的操作表达式){ for(里层的初始化变量;里层的条件表达式;里层的操作表达式){ //执行语句 } }
-
我们可以把里面的循环看作是外层循环的语句
-
外层每循环一次,里面的循环执行全部
-
代码验证
for (let i =1;i <= 3;i++){ console.log('这是外层循环第'+ i +'次'); for(let j = 1;j <= 3;j++){ console.log('这是内层循环第'+ i +'次'); } }
(3)while循环
-
语法结构
while(条件表达式){ //循环体 }
-
执行思路:当条件表达式为ture,则执行循环体;否则,退出循环
-
代码验证
let num = 1; while (num <= 100){ console.log('hello'); num++;//防止死循环 }
-
里面应该也有计数器,初始化变量
-
里面应该也有操作表达式,完成计数器的更新,防止死循环
(4)do while循环
-
语法结构
do { //循环体 }while(条件表达式)
-
执行思路:跟while不同的地方在于 do while 先执行一次循环体,再判断条件,如果条件表达式结果为真,则继续执行循环体,否则退出循环。
-
do while 循环体至少执行一次。
-
代码验证
let i = 1; do { console.log('how are you'); i++; }while(i <= 100)
(5)循环小结
- 如果是用来计数的、和数字相关的,三者使用基本相同,但是我们更喜欢用for
- while 和 do…while 可以做更复杂的判断条件,比for循环灵活一些
- while 和 do…while 执行顺序不一样,while 先判断后执行,do…while 先执行一次,再判断执行
(6)continue 关键字
用于立即跳出本次循环,继续下一次循环
-
代码实现
for (let i = 1;i <= 5;i++){ if (i == 3){ continue; } console.log('我正在吃第'+ i +'个苹果') ; }
(7)break 关键字
用于立即跳出整个循环(循环结束)
-
代码实现
for (let i = 1;i <= 5;i++){ if (i == 3){ break; } console.log('我正在吃第'+ i +'个苹果') ; }
3.6 数组
数是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的优雅方式。
3.6.1 数组的创建方式
(1)利用 new 创建数组
let arr = new Array();//创建了一个空的数组
let arr1 = new Array(2);//这个 2 表示数组的长度为 2 ,里面有两个空的数组元素
let arr2 = new Array(2,3);//这样写表示 里面有两个数组元素 是 2 和 3
(2)利用数组字面量创建数组
let arr = [];//创建了一个空的数组
let arr1 = [1,2,'pink',ture];//我们数组里面的数据一定用逗号分隔
3.6.2 获取数组中的元素
数组的索引
索引(下标):用来访问数组元素的序号(数组下标从0开始)
-
获取数组元素
-
格式: 数组名[索引号]
//定义数组 let arrStus = [1,2,3]; //获取数组中的第二个元素 alert(arrStus[2]);
-
3.6.3 遍历数组
遍历就是把数组中的每个元素从头到尾都访问一次(类似于我们每天早上学生的点名)
let arr = ['red','green','blue'];
for (let i = 0;i < arr.length;i++){
console.log(arr[i]);
}
//1.因为我们的数组索引号从 0 开始,所以 i 必须从 0 开始 i < 3
//2.输出的时候 arr[i] i 计数器当索引号来用
//3.arr.length 动态监测数组元素的个数
3.6.4 数组中新增的元素
通过修改length长度以及索引号增加数组元素
(1)通过修改 length 长度新增数组元素
-
可通过修改 length 长度来实现数组扩容的目的
-
length 属性是可读写的
let arr = [1,2,3,4,5]; arr.length = 7; console.log(arr[6]);//undefined console.log(arr[7]);//undefined
(2)修改索引号 追加数组元素
let arr1 = [1,2,3];
arr1[3] = 'pink';
console.log(arr1);
- 不要直接给 数组名 赋值,否则里面的数组元素都会被覆盖
3.6.5 冒泡排序
冒泡排序:是一种算法,把一系列的数据按照一定的顺序进行排列显示(从小到大或从大到小)
原理:重复的走访要排列的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复的进行直到没有再需要交换的元素,也就是该数列已经排序完成。
let arr = [4,1,2,3,5];
for (let i = 0;i <= arr.length - 1;i++){
for (let j = 0;j <= arr.length - i - 1;j++){
if (arr[j] > arr[j + 1]){
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j+1] = temp;
}
}
}
console.log(arr);
3.7 函数
3.7.1 函数的概念
- 函数:就是封装了一段可被重复调用执行的代码块,通过此代码块可以实现大量代码的重复使用
3.7.2 函数的使用
-
声明函数 (关键字 function)
function 函数名(){ //函数体 }
- 函数是做某件事情,函数名一般是动词
- 函数不调用自己不执行
-
调用函数
函数名();//调用函数的时候千万不要忘记加小括号
3.7.3 函数的封装
- 把一个或多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口
3.7.4 函数的参数
(1)参数的作用:
在函数内部有些值不固定,我们可以通过参数在调用函数时传递不同的值进去
-
函数的参数可以有,也可以没有,个数不限
function 函数名(形参1,形参2...){// 形参 形式上的参数 //函数体 } 函数名(实参1,实参2...)// 实参 实际上的参数
(2)函数形参和实参个数不匹配问题
function getSum(num1,num2) {
console.log(num1 + num2);
}
-
如果实参和形参的个数一致,则正常输出结果
getSum(1,2);// 3
-
如果实参的个数多于形参的个数
getSum(1,2,3);// 3
-
如果实参的个数小于形参的个数
形参可以看作是一个不用声明的变量,num2 是一个变量但是没有接受值 它的值就是undefined
getSum(1);// NaN
3.7.5 函数的返回值
把输出语句写在函数内部是不合理的(比如console.log),这时候我们就需要返回值
(1)return 语句
我们函数只是实现某种功能,最终的结果需要返回给函数的调用者 函数名(),这是通过 return 来实现的
只要函数遇到 return,就把后面的结果返回给函数的调用者;相当于:函数名() = return 后面的结果
终止函数:return语句之后的代码不被执行
return 只会返回一个结果(最后一个),若要返回多个结果,可用数组来实现
return [num1+num2,num1-num2,num1*num2,num1/num2]
-
格式
function 函数名() { return 需要返回的结果; } 函数名(); console.log(函数名());
-
代码实操
//求任意两个数的和 function getSum(num1,num2){ return num1 + num2; } console.log(getSum(1,2));
(2)函数的返回值注意事项
-
函数如果有 return 则返回的是 return 后面的值;如果没有 return 则返回 undefined
function fun1(){ return 666; } console.log(fun1());// 返回 666 ------------ function fun2(){ } console.log(fun2());// 返回 undefined
(3)break ,cntinue ,return的区别
- break:结束当前循环体
- continue:跳出本次循环,继续执行下次循环
- return:不仅可以退出循环,还能返回 return 语句中的值,同时还可以结束当前循环体内的代码
3.7.6 arguments 的使用
-
在JS中,arguments 实际上是当前函数的一个内置对象,arguments 对象中存储了传递的所有实参。
- 当我们不确定有多少个参数传递的时候,可以用 arguments 来获取。
-
arguments 展示形式是一个伪数组,因此可以进行遍历。伪数组的特点:
- 具有 length 属性
- 按索引方式储存数据
- 不具有数组的push,pop等方法
-
代码实操
//翻转数组 function reverse(){ let newArr = []; for (let i = arguments.length - 1;i >= 0; i--){ newArr[newArr.length] = arguments[i] } return newArr } let res = reverse('red','yellow','green','blue'); console.log(res);
3.7.8 函数是可以相互调用的
function fn1(){
console.log(11);
fn(2);//在 fn1 函数里面调用了 fn2 函数
}
fn1();
function fn2(){
console.log(22);
}
3.7.9 函数的两种声明方式
(1)利用函数关键字(function)自定义函数(命名函数)
function fn(){
}
fn();
(2)函数表达式(匿名函数)
- 没有定义函数名,只有变量名
- 函数表达式声明方式跟声明变量差不多,只不过变量里面存的是值,而函数表达式里面存的是函数
let 变量名 = function(){
console.log('我是函数表达式');
}
变量名();
3.8 JS预解析
- js 引擎运行 js 分为两步 :预解析、代码执行
- 预解析分为 变量预解析(变量提升) 和函数与解析(函数提升)
- 变量提升:就是把所有的变量提升到当前作用域的最前面,不提升赋值操作。
- 函数提升:就是把所有的函数声明提升到当前作用域的最前面,不调用函数。
- 预解析 js 会把里面所有的 var 还有 function 提升到当前作用域的最前面
- es6 中使用 let ,没有变量提升
3.9 对象(object)
3.9.1 什么是对象
在 JS 中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等
- 对象是由属性和方法组成的
- 属性:事物的特征,在对象中用属性来表示(常用名词)
- 方法:事物的行为,在对象中用方法来表示(常用动词)
3.9.2 创建对象的三种方式:
-
利用字面量创建对象:就是花括号{}里包含了表达这个事物(对象)的属性和方法
-
创建对象:
-
里面的属性或者方法我们采取键值对的方式 属性名 :属性值
-
多个属性方法或者方法中间用逗号隔开
-
方法冒号后面跟的是个匿名函数
let obj = { uname:'小羊', age:18, sex:'男', sayHi:function(){ console.log('hi~'); } }
-
-
使用对象
-
调用对象的属性,我们采用 对象名.属性名
console.log(obj.uname);
-
调用属性还有另外一种方法 对象名[‘属性名’]
console.log(obj['age']);
-
调用对象方法的方法 对象名.方法名 千万别忘记小括号
obj.sayHi();
-
-
-
利用 new Object 创建对象
-
创建对象
-
利用等号赋值的方法添加对象的属性和方法
-
每个属性和方法之间用分号结束
let obj = new Object;//创建了一个空的对象 obj.uname = '小羊'; obj.age = 18; obj.sex = '男'; obj.sayHi = function() { console.log('hi~') }
-
-
使用对象
- 同自变量调用对象一样
-
-
利用构造函数创建对象
为什么需要构造函数:前面两种方式一次只能创建一个对象
因此我们可以利用函数的方法,重复这些相同的代码,我们就把这个函数称为 构造函数
构造函数:就是把对象里一些相同的属性和方法抽象出来封装到函数里面
-
构造函数的语法格式
- 构造函数名首字母必须大写
- 构造函数不需要返回 return 就可以返回结果
function Star(uname,age,sex) { this.name = uname; this.age = age; this.sex = sex; this.sing = function(){ console.log() } }
-
调用构造函数(必须使用new)
let ldh = new Star('刘德华',18,'男'); console.log(ldh.name); console.log(ldg['age']); ldh.sing('冰雨');
-
-
构造函数和对象
-
我们利用构造函数创建对象的过程也称为对象的实例化
-
构造函数 类似于 java 语言里面的类(Star)
function Star(uname,age,sex) { this.name = uname; this.age = age; this.sex = sex; this.sing = function(){ console.log() } }
-
对象 是一个具体的事物 类似于类的实例化(ldh):
let ldh = new Star('刘德华',18,'男');
-
3.9.3 变量、属性、函数、方法的区别
-
变量和属性
- 相同点:都是用来存储数据的
- 不同点:
- 变量是单独声明并赋值,使用时可以直接写变量名(单独存在);
- 属性是在对象里面的,不需要声明,使用时必须是 对象.属性。
-
函数和方法
-
相同点:都是用来实现某种功能的
-
不同点:
- 函数是单独声明,并且调用的(单独存在)
- 方法是在对象里面的,调用的时候 对象.方法()
-
3.9.4 new 关键字执行过程
- new 构造函数首先在内存中创建一个空的对象
- this 就会指向刚才创建的空对象
- 执行构造函数里面的代码,给空对象添加属性和方法
- 返回这个对象(所以不需要return)
3.9.5 遍历对象
对象里的属性和方法是无序的,所以不能使用 for 循环遍历
for…in 语句用于对数组或者对象的属性进行循环操作。
-
语法格式
for (变量 in 对象) { }
-
代码实操
-
我们使用 for…in 里面的变量,一般写 k 或者 key
let obj = { name : 'sheep', age : 18, sex : '女', fn : function(){} } //遍历对象 for (let k in obj) { console.log(k);// k 变量 输出得到属性名 console.log(obj[k]);// obj[k] 输出得到属性值 }
-
3.10 内置对象
- JS中对象分为三种:自定义对象、内置对象、浏览器对象
- 内置对象就是指 JS 语言自带的一些对象,供开发者使用,并提供了一些常用的或者是最基本而必要的功能(属性和方法),帮助我们快速开发
- JS 提供了多个内置对象:Math、Date、Array、String等
3.10.1 查阅文档
-
MDN
https://developer.mozilla.org/zh-CN/
3.10.2 Math
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AS0h6wha-1668609019257)(https://gitee.com/colohh/image_bed/raw/master/img/Math%E5%AF%B9%E8%B1%A1.png)]
-
不是构造函数,所以我们不需要 new 来调用,而是直接使用里面的属性和方法即可
-
调用属性
//圆周率 console.log(Math.PI);
-
调用方法
//取最大值 console.log(Math.max(1,99,3))
-
-
随机数方法 Math.random
-
random() 返回一个[ 0,1 )之间随机的小数
-
这个方法里面不跟参数
-
我们想要得到这两个数之间的随机整数 并且 包含这两个整数
function getRandom(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值 } console.log(getRandom(1,10));
-
3.10.3 Date 日期对象
-
Date 是一个构造函数,必须使用 new 来调用创建我们的日期对象(必须实例化)
let date = new Date(); console.log(date);
-
如果没有参数,则返回当前系统的当前时间
参数常用的写法
数字型 2019,10,1
let date1 = new Date(2019,10,1); console.log(date1);
字符串型 ‘2019-10-1 8:8:8’
let date2 = new Date( '2019-10-1 8:8:8'); console.log(date2);
-
日期格式化
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NsJgqam7-1668609019257)(https://gitee.com/colohh/image_bed/raw/master/img/Date%E5%AF%B9%E8%B1%A1.png)]
-
代码实操
let date = new Date();//实例化 console.log(date.getFullYear());//返回当前日期的年 console.log(date.getMonth() + 1);//返回月份 month(0 - 11); console.log(date.getDay() + 1);//返回星期几 (周六返回6;周日返回0)
-
获取Date的总的毫秒数(时间戳)(距离1970.01.01过了多少毫秒数)
-
通过 valueOf()
let date = new Date(); console.log(date.valueOf());
-
通过 getTime()
let date = new Date(); console.log(date.getTime());
-
简单写法 ==+==new Date()
let date1 = +new Date();
-
h5 新增写法
console.log(Date.now());
-
3.10.4 数组对象
(1)检测是否为数组
-
instanceof 运算符,可以用来检测是否为数组
let arr = []; let obj = {}; console.log(arr instanceof Array);//true console.log(obj instanceof Array);//false
-
Array.isArray(参数); h5新增
let arr = []; console.log(Array.isArray(arr));//true
(2)添加删除数组元素的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MHfFKHS4-1668609019258)(https://gitee.com/colohh/image_bed/raw/master/img/%E6%B7%BB%E3%80%81%E5%88%A0%E6%95%B0%E7%BB%84%E5%85%83%E7%B4%A0%E7%9A%84%E6%96%B9%E6%B3%95.png)]
-
push() 在数组的末尾,添加一个或多个数组元素
-
push() 括号里参数直接写数组元素
-
push 完之后,返回的结果是新数组的长度
let arr.push(4,'pink'); console.log(arr.push(4,'pink'))// 5
-
-
unshift() 在数组的开头,添加一个或多个数组元素
-
unshift() 括号里参数直接写数组元素
-
unshift 完之后,返回的结果是新数组的长度
let arr = [1,2,3]; arr.unshift(4,'pink'); console.log(arr.unshift(4,'pink'))// 5
-
-
pop() 删除数组的最后一个元素
-
pop() 里不写参数
-
返回值是被删掉的数组元素
let arr = [1,2,3]; arr.pop(); console.log(arr.pop());// 3
-
-
shift() 删除数组的第一个元素
-
shift() 里不写参数
-
返回值是被删掉的数组元素
let arr = [1,2,3]; arr.shift(); console.log(arr.shift());// 1
-
(3)数组排序
-
翻转数组
-
reverse()
let arr = ['pink','red','blue']; arr.reverse(); console.log(arr);
-
-
冒泡排序
-
sort()
let arr = [8,3,6,4,5]; arr.sort(function(a - b){ return a - b;//升序的顺序排列 return b - a;//降序的顺序排列 }); console.log(arr1);
-
(4)数组索引方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0iRPDmG0-1668609019258)(https://gitee.com/colohh/image_bed/raw/master/img/%E6%95%B0%E5%AD%97%E7%B4%A2%E5%BC%95%E6%96%B9%E6%B3%95.png)]
-
indexOf(数组元素,[起始位置])
-
只返回第一个满足条件的数组元素的索引号
-
如果在该数组里找不到元素,则返回 -1
let arr = ['pink','red','blue','green','blue']; console.log(arr.indexOf('blue'));// 2 返回数组元素的索引号
-
-
lastIndexOf(数组元素)
-
类似于 indexOf(),不过 lastIndexOf()是从后往前查找
-
如果在该数组里找不到元素,则返回 -1
let arr = ['pink','red','blue','green','blue']; console.log(arr.lastIndexOf('blue'));// 4
-
(5)数组转换为字符串
-
toString()
-
直接转换为字符串
let arr = [1,2,3]; console.log(arr.toString());//1,2,3
-
-
join(‘分隔符’)
-
更高级,join() 可以自定义分隔符
let arr = [1,2,3]; console.log(arr.join());// 1,2,3 console.log(arr.join('-'));//1-2-3 console.log(arr.join('&'));//1&2&3
-
3.10.5 字符串对象
(1)基本包装类型
复杂数据类型才有 属性和方法
简单数据类型为什么会有 length 属性呢
-
基本包装类型:就是把简单数据类型(三个:String、Number、Boolean)包装成为了复杂数据类型,这样基本数据类型就有了属性和方法
// 底层流程展示 let str = 'sheep'; console.log(str.length); //1. 把简单数据类型包装为复杂数据类型 let temp = new String('andy'); //2. 把临时变量的值给 str str = temp; //3. 销毁这个临时变量 temp = null;
(2)字符串的不可变性
- 值不可变:看上去是改变了内容,实际上是改变字符串变量名指向的地址(好像指针噢),内存中开辟了一个新的内存空间存了一个新值(因此不要大量的拼接字符串)
(3)根据字符返回位置
字符串的所有方法,都不会修改字符串本身(字符串本身是不可变的),操作完成会返回一个新的字符串
-
indexOf(‘字符’,[起始位置])
let str = '改革春风吹满地,春天来了'; console.log(str.indexOf('春'));// 2 console.log(str.indexOf('春',3));// 8 从索引号是 3 的位置开始往后查找
-
lastIndexOf(‘字符’,[起始位置])
(4)根据位置返回字符(重点)
-
charAt(index)
-
获取指定位置处的字符
let str = 'sheep'; console.log(str.charAt(1));// h
-
利用 charAt( ) 遍历字符串
for (i = 0; i < str.lenghth ;i++) { console.log(str.charAt(i)); }
-
-
charCodeAt(index)
-
返回相应索引号的字符ASCII值 目的:判断用户按下了哪个键
let str = 'sheep'; console.log(charCodeAt(1));// 104
-
附 ASCII 码表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zPVPRo8a-1668609019259)(https://gitee.com/colohh/image_bed/raw/master/img/ASCII%E7%A0%81%E8%A1%A8.PNG)]
-
-
str[index]
- 获取指定位置处的字符(HTML5)
let str = 'sheep'; console.log(str[1]);// h
(5)字符串的基本操作方法(重点)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aNL3cGAr-1668609019259)(https://gitee.com/colohh/image_bed/raw/master/img/%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E6%93%8D%E4%BD%9C%E6%96%B9%E6%B3%95.png)]
(6)字符串的连接
-
concat(str1,str2…)
-
用于连接两个或多个字符串,拼接字符串,等效于+ ,+更常用
let str = 'andy'; console.log(str.concat('red'));// andyred
-
(7)自定义位置索引
-
substr(start,length)
-
从 start 位置开始索引,length 取的个数
let str = '改革春风吹满地'; console.log(str.substr(2,2));// 春风
-
-
slice(start,end)
- 从 start 位置开始,截取到 end 位置(不包含end)
-
substring(start,end)
- 从 start 位置开始,截取到 end 位置(不包含end),基本和 slice 相同,但不接受负值
(8)替换字符
-
replace(‘被替换的字符’,‘替换为的字符’)
-
只替换第一个符合要求的字符
let str = 'andy'; console.log(str.replace('a','b'));
-
(9)字符串转换为数组
-
split(‘分隔符’)
-
分隔符取决于字符串用什么符号来把它们分开的
let str1 = 'red,pink,blue'; console.log(str1.split(','));//[red,pink,blue] let str2 = 'red&pink&blue'; console.log(str2.split('&'));//[red,pink,blue]
-
3.11 JS 简单数据类型和复杂数据类型
3.11.1 简单类型与复杂类型
-
简单类型又叫做值类型,在存储时变量中存储的是值本身,因此叫做值类型
string , number , boolean , undefined , null
-
其中 null 比较特殊 typeof 它返回的是一个空的对象(object)
所以如果有一个变量我们以后打算存储为对象,暂时没想好放什么,这个时候就给 null
let timer = null; console.log(typeof timer);//object
-
-
复杂类型又叫做引用类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用类型
通过 new 关键字创建的对象(系统对象,自定义对象):如Object , Array , Date 等
3.11.2 堆和栈
JS 里没有堆和栈的概念,只是帮助我们方便理解代码的执行方式
- 分配区别
- 栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;简单数据类型存放到栈里面
- 2、堆(操作系统)∶存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型存放到堆里面
3.11.3 简单类型的内存分配
- 简单数据类型存放到栈里面
- 在栈里面直接存放的是值
3.11.4 复杂类型的内存分配
- 复杂数据类型存放到堆里面
- 首先在栈里面存放地址 用十六进制表示,然后这个地址指向堆里面存储的数据
3.11.5 简单类型传参
-
函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。
function fn(a) { a++; console.log(a);// 11 } let x = 10; fn(x); console.log(x);// 10
3.11.5 复杂类型传参
-
函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。
function Person(name) { this.name = name; } function f1(x) { console.log(x.name);// 2.这个输出是:刘德华 x.name = '张学友'; console.log(x.name);// 3.这个输出是:张学友 } let p = new Person('刘德华'); console.log(p.name);// 1.这个输出是:刘德华 f1(p); console.log(p.name);// 4.这个输出是:张学友
-
图解上面代码:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FFgnVSXQ-1668609019259)(https://gitee.com/colohh/image_bed/raw/master/img/%E5%A4%8D%E6%9D%82%E7%B1%BB%E5%9E%8B.png)]
.split(‘,’));//[red,pink,blue]let str2 = ‘red&pink&blue’;
console.log(str2.split(‘&’));//[red,pink,blue]
3.11 JS 简单数据类型和复杂数据类型
3.11.1 简单类型与复杂类型
-
简单类型又叫做值类型,在存储时变量中存储的是值本身,因此叫做值类型
string , number , boolean , undefined , null
-
其中 null 比较特殊 typeof 它返回的是一个空的对象(object)
所以如果有一个变量我们以后打算存储为对象,暂时没想好放什么,这个时候就给 null
let timer = null; console.log(typeof timer);//object
-
-
复杂类型又叫做引用类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用类型
通过 new 关键字创建的对象(系统对象,自定义对象):如Object , Array , Date 等
3.11.2 堆和栈
JS 里没有堆和栈的概念,只是帮助我们方便理解代码的执行方式
- 分配区别
- 栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;简单数据类型存放到栈里面
- 2、堆(操作系统)∶存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型存放到堆里面
3.11.3 简单类型的内存分配
- 简单数据类型存放到栈里面
- 在栈里面直接存放的是值
3.11.4 复杂类型的内存分配
- 复杂数据类型存放到堆里面
- 首先在栈里面存放地址 用十六进制表示,然后这个地址指向堆里面存储的数据
3.11.5 简单类型传参
-
函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。
function fn(a) { a++; console.log(a);// 11 } let x = 10; fn(x); console.log(x);// 10
3.11.5 复杂类型传参
-
函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。
function Person(name) { this.name = name; } function f1(x) { console.log(x.name);// 2.这个输出是:刘德华 x.name = '张学友'; console.log(x.name);// 3.这个输出是:张学友 } let p = new Person('刘德华'); console.log(p.name);// 1.这个输出是:刘德华 f1(p); console.log(p.name);// 4.这个输出是:张学友
-
图解上面代码:
[外链图片转存中…(img-FFgnVSXQ-1668609019259)]