数组
数组的概念
数组就是一组数据的集合,并且存储在单个变量名下
数组的创建方式
利用new创建数组
var 数组名 = new Array();
var arr = new Array();//创建了一个空数组
利用数组字面量创建数组(常用)
var 数组名 = [];
var arr = [];//创建了一个空数组
声明数组并赋值称为数组的初始化
里面的数据称为元素,可以为任意数据类型
var arr1 = [1,'我',null,undefined,true,false,2]
获取数组中的元素
索引(下标):用来访问数组元素的序号,从0开始排序即表示第一个元素的索引为0
获取(访问)数组元素格式:数组名[索引]
var arr1 = [1,'我',null,undefined,true]
console.log(arr1[0]);//1
console.log(arr1[1]);//我
console.log(arr1[2]);//null
访问没有的元素,返回undefined
var arr1 = [1,'我',null,undefined,true]
console.log(arr1[5]);//undefined
遍历数组
数组长度:length,数组元素的个数。遍历就是获取每一个元素。
利用for循环遍历,数组长度调用:数组名.length
遍历返回的是所有的元素,不是新数组
var arr = ['张三','李四','王五','赵六']
for (var i = 0; i < arr.length; i++) {
console.log(i);//获取数组索引// 0 1 2 3
console.log(arr[i]); //获取数组元素// 张三 李四 王五 赵六
}
案例1:数组求和及平均值
var arr = [11, 22, 33, 22, 11]
var sum = 0;
for (var i = 0; i < arr.length; i++) {
sum += arr[i]
}
var even = sum / arr.length
console.log(sum);//99
console.log(even);//19.8
案例2:求数组中的最大值/最小值
var arr = [11, 22, 33, 22, 11]
var max = arr[0]
for (var i = 1; i < arr.length; i++) {
if (max <= arr[i]) {
max = arr[i]
}
}
console.log(max);//33
var min = arr[0]
for (var i = 1; i < arr.length; i++) {
if (min >= arr[i]) {
min = arr[i]
}
}
console.log(min);//11
案例3:将数组转换为分割字符串
var arr = ['hello', 'baby', 'you', 'are', 'handsome']
var str = ''
for (var i = 0; i < arr.length; i++) {
str += arr[i] + '|'
}
console.log(str);//hello|baby|you|are|handsome|
数组中新增元素
通过修改length长度新增数组
var arr = ['hello', 'baby', 'you', 'are', 'handsome']
arr.length = 7
console.log(arr);//['hello', 'baby', 'you', 'are', 'handsome', 空属性 × 2]
console.log(arr[7]);//undefined
若修改数组长度比原来小则表示截取数组
var arr = ['hello', 'baby', 'you', 'are', 'handsome']
arr.length = 2
console.log(arr);//['hello', 'baby']
修改索引号来新增数组元素(追加)
var arr = ['hello', 'baby']
arr[2] = 'loveyou'
console.log(arr);//['hello', 'baby', 'loveyou']
若原索引就有元素,则表示修改数组元素
var arr = ['hello', 'baby']
arr[1] = 'world'
console.log(arr);//['hello', 'world']
案例1:创建一个空数组,添加[1,10]
var arr = []
for (var i = 0; i < 10; i++) {
arr[i] = i + 1
}
console.log(arr);//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
案例2:筛选数组,将数组中大于等于10的数筛选出来并放入新数组
思路1:在遍历数组外:
声明一个空数组用来放入新元素 var newArr = [];
声明一个变量赋值为0,表示新数组的索引为0 var j = 0;
newArr[j] = 原数组[i]; j++;满足条件索引加1
var arr = [12, 3, 65, 2, 55, 9, 62, 22, 5, 10]
var newarr = []
var j = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] >= 10) {
newarr[j] = arr[i];
j++;
}
}
console.log(newarr);//[12, 65, 55, 62, 22, 10]
思路2:newarr[newarr.length] = arr[i];
空数组长度为0,添加元素后长度依次加1,刚好和新数组索引对应
var arr = [12, 3, 65, 2, 55, 9, 62, 22, 5, 10]
var newarr = []
//刚开始 新数组长度为0
for (var i = 0; i < arr.length; i++) {
if (arr[i] >= 10) {
newarr[newarr.length] = arr[i];
}
}
console.log(newarr);//[12, 65, 55, 62, 22, 10]
删除指定数组元素
案例1:生成的新数组不含0
var arr = [1, 3, 65, 2, 0, 9, 62, 22, 0, 10]
var newArr = []
for (var i = 0; i < arr.length; i++) {
if (arr[i] != 0) {
newArr[newArr.length] = arr[i]
}
}
console.log(newArr);//[12, 65, 55, 62, 22, 10]
案例2:翻转数组,生成的新数组翻转
var arr = [1, 3, 65, 2, 0]
var newArr = []
for (var i = arr.length - 1; i >= 0; i--) {
newArr[newArr.length] = arr[i]
}
console.log(newArr);//[0, 2, 65, 3, 1]
案例3:数组排序(冒泡排序)
一次比较两个元素 ,如果他们的顺序错误就把他们交换过来。
从小到大或从大到小排序
思路
外循环:表示所需要的趟数(遍数),趟数为arr,length-1;
内循环:表示每一趟交换的次数,每一趟的次数为:arr.length-i-1;
前一个数与后一个数比较,若前一个数大,则交换
var arr = [1, 3, 65, 2, 0]
for (var i = 0; i < arr.length - 1; i++) {
for (var j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
console.log(arr);
从大到小
var arr = [1, 3, 65, 2, 0]
for (var i = 0; i < arr.length - 1; i++) {
for (var j = 0; j < arr.length - i - 1; j++) {
if (arr[j] < arr[j + 1]) {
var temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
console.log(arr);//[65, 3, 2, 1, 0]
函数
函数的概念
做某件事或实现某个功能
作用,封装一段代码,使用时调用名称即可,不用再重写代码。可以提高代码的复用率,减小代码量。
函数的使用
函数使用分两步 : 1.声明函数 2.调用函数
没有调用的函数无法使用,函数调用前必须声明函数
声明函数
格式:(其中一种,利用函数关键字自定义函数,也叫命名函数)
function 函数名() {
代码块
}
举例:
function sayHi() {
console.log('hi!boys and girls');
}
只是声明函数,没有调用就无法使用即不会运行,给函数命名推荐动词
调用函数
格式:
函数名();
举例接上:在控制台打印了如下字符串
sayHi();//hi!boys and girls
案例:利用函数求[1,100]的累加和
function getSum() {
var sum = 0;
for (var i = 1; i <= 100; i++) {
sum += i
}
console.log(sum);
}
getSum();//5050
不能在函数外直接调用函数内嵌套的函数
var num = 10;
function fun1() {
var num = 20;
console.log(num);
function fun2() {
var num = 30;
console.log(num);
}
fun2()
}
fun2()//fun2 is not defined
函数的参数
参数概念与格式
函数的参数分为形参与实参
作用:利用函数参数的传递可以实现一个函数实现不同要求
形参:形式参数,在函数声明的小括号里
实参:实际参数,在函数调用的小括号里
function 函数名(形参1,形参2,...) {
代码块
}
函数名(实参1,形参2,...);
参数传递
实参把数据传递给形参
函数的参数可有可无可多个,实参会把值传递给实参,类似于给形参赋值
function cook(menu) {
console.log(menu);
}
cook('莲藕盒子');//莲藕盒子
cook('狼牙土豆')//狼牙土豆
案例1:利用函数求任意两个数的和
function getSum(num1, num2) {
console.log(num1 + num2);
}
getSum(1, 2)//3
getSum(66, 33)//99
案例2:利用函数求任意两数之间的和
function getSum(start, end) {
var sum = 0;
for (var i = start; i <= end; i++) {
sum += i;
}
console.log(sum);
}
getSum(55,100)//3565
getSum(1,10)//55
getSum()//0
ps:多个参数之间用逗号隔开,形参可以看作不用声明的变量
console.log(undefined <= undefined);//false//关系运算符隐式转换为number
console.log(Number(undefined));//NaN
console.log(Number(undefined));//NaN
若实参的个数多余形参的个数
会顺序取到形参的个数,正常执行
getSum(1,10,50)//55
若实参的个数小于形参的个数
可以看作缺少的实参没有给形参赋值,即未被赋值的形参值为undefined
getSum(1,)//0
返回值
概念与格式
函数只现实某种功能,最终的结果需要返回给函数的调用者
格式
return 函数结果;
function 函数名() {
return 需要返回的结果
}
函数名();
例子:
function getSum(num1,num2) {
return num1 + num2
}
console.log(getSum(66,33));//99
案例:利用函数求任意一个数组中的最大值
function getMax(arr = []) {
var max = arr[0]
for (var i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i]
}
}
return max
}
console.log(getMax([2,6,8,5,4]));//8
console.log(getMax());//undefined
可以给形参一个默认值,防止传参有误时报错,通常用一个变量来接收结果
return注意点
return还表示终止函数,return后面的代码不会被执行
function fn(num1, num2) {
return num1 + num2
console.log("我不能被执行");
}
console.log(fn(1, 2));//3
return只能返回一个值,值若有多个值用逗号隔开,则返回最后一个值
function fn(num1,num2) {
return num1,num2
}
console.log(fn(1,2));//2
若想获得多个值可返回一个数组
若函数没有return,则返回undefined
function fn(num1, num2) {
var sum = num1 + num2
}
console.log(fn(1, 2));//undefined
arguments的使用
当我们不确定有多少个参数传递的时候,可以用arguments来获取。在JavaScript中, arguments实际上
是当前函数的一个内置对象。所有函数都内置了一个arguments对象, arguments对象中存储了传递的
所有实参。
function fn() {
console.log(arguments);
}
fn(1,2,3);
![](https://i-blog.csdnimg.cn/blog_migrate/dcdcc4309d5c40ad4800cf45561f1e60.png)
arguments是一个伪数组,具有length属性,按照索引的方式进行存储,但是没有真正数组的方法
function fn() {
sum = 0;
for (let i = 0; i < arguments.length; i++) {
sum += arguments[i]
}
return sum
}
var res = fn(1, 2, 3, 4, 5, 6, 7, 8, 9);
console.log(res);//45
var arr = []
for (let i = 0; i < arguments.length; i++) {
arr[arr.length]= arguments[i]
}
return arr
}
var res = fn(1, 2, 3, 4, 5, 6, 7, 8, 9);
console.log(res);
只有函数才有arguments对象
案例1:求任意个数的最大值
function getMax() {
var max = arguments[0]
for (var i = 0; i < arguments.length; i++) {
if (max < arguments[i]) {
max = arguments[i]
}
}
return max
}
var res = getMax(55, 33, 8, 97, 66, 0, 35);
console.log(res);//97
案例2:利用函数翻转任意一个数组
function getRverse(arr) {
var newArr = [];
for (var i = arr.length - 1; i >= 0; i--) {
newArr[newArr.length] = arr[i]
}
return newArr
}
var res = getRverse([55, 33, 8, 97, 66, 0, 35]);
console.log(res);//[35, 0, 66, 97, 8, 33, 55]
案例3:利用函数,对数组排序-冒泡排序
function getRverse(arr = []) {
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]) {
var temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
return arr
}
var res = getRverse([55, 33, 8, 97, 66, 0, 35]);
console.log(res);//[0, 8, 33, 35, 55, 66, 97]
案例4:判断是否为闰年
function isYears(a) {
var flag;
a % 4 == 0 && a % 100 != 0 || a % 400 == 0 ? flag = true : flag = false
return flag
}
var res = isYears(2000);
console.log(res);
函数调用另一个函数
function fn1() {
console.log(11);
fn2();//在函数里调用函数
}
fn1();
function fn2() {
console.log(22);
}
案例:用户输入年份,输出当前年份2月天数
function backDay() {
var years = prompt("请输入年份")
if (isYears(years)) {
console.log("2月有29天");
} else {
console.log("2月有28天");
}
}
backDay();//调用函数
function isYears(years) {
var flag;
years % 4 == 0 && years % 100 != 0 || years % 400 == 0 ? flag = true : flag = false
return flag
}
函数的另一种声明方式
函数表达式(匿名函数)
格式
var 变量名 = function () {
代码块
}
变量名();
var fn = function () {
console.log("hello");
}
fn();//hello
fn是变量名不是函数名
作用域
概念
JavaScript作用域:就是代码名字(变量)在某个范围内起作用和效果
在es5中作用域分为:全局作用域 局部作用域/函数作用域
全局作用域:变量整个script标签或单独的js文件中起作用
局部作用域:变量只在函数内部起作用
var num = 10;
function fn() {
var num = 20;
console.log(num);//20
}
fn()
console.log(num);//10
变量的作用域
全局变量
在全局作用域下的变量,全局都可以使用(在函数内部没有声明,直接赋值属于全局变量)
var num = 10;
function fn() {
console.log(num);//10
}
fn()
console.log(num);//10
若在函数内部没有声明,直接赋值属于全局变量
function fn() {
var num1 = 10;
console.log(num1);//10
num2 = 20;
}
fn();
console.log(num2);//20
全局变量只有关闭浏览器式才会销毁
局部变量
在局部作用域下的变量,函数内才起作用
function fn() {
var num = 10;
return num
}
console.log(fn());//10
console.log(num);//报错,未定义
函数的形参也看作局部变量
function fn(num) {
}
fn();
console.log(num);//报错,未被定义
局部变量执行完自己的代码就销毁
块级作用域
块级作用域 ,即{}内才起作用
es5中没有块级作用域,es6中才有块级作用域
举例:在es5中,在块级作用域外可以使用块级作用域内声明的变量
if (3 < 5) {
var num = 10
}
console.log(num);//10
若在es6中就会报错
if (3 < 5) {
let num = 10
}
console.log(num);//报错
作用域链
内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称为作用域链
遵守就近原则,自己有声明就访问自己的变量,自己没有声明就逐级向上找变量
var num = 10;
function fun1() {
var num = 20;
console.log(num);//20
function fun2() {
console.log(num);//20
}
fun2()
}
fun1()
JavaScript预解析
概念
1.JavaScript代码是由浏览器中的JavaScript解析器来执行的。JavaScript 解析器在运行JavaScript代码的时候分为两步:预解析和代码执行。
2.预解析js引擎会把js里面所有的var还有 function 提升到当前作用域的最前面
3.代码执行 代码按照书写顺序从上往下执行
预解析分为变量预解析(变量提升)和函数预解析(函数提升)
变量提升
把所有的变量声明提升到当前作用域最前面,只提升声明,不做赋值操作
console.log(num);//undefined
var num = 20;
函数提升
把所有的函数声明提升到当前作用域的最前面,不调用函数
fn()
function fn() {
console.log(1);//1
}
函数表达式调用必须写在函数表达式的下面,因为函数表达式用变量接收函数
fn2()//报错
var fn2 = function () {
console.log(2);
}
案例1:
var num = 10;
fun();
function fun() {
console.log(num);//undefined
var num = 20;
}
案例2:
var num = 10;
function fun() {
console.log(num);//undefined
var num = 20;
console.log(num);//20
}
fun()
案例3:
var a = 10;
f1();
function f1() {
var b = 9;
console.log(a);//undefined
console.log(b);//9
var a = '123';
}
案例4:
var a = b = c = 9; 相当于 var a = 9; b = 9; c = 9; b和c直接赋值,是全局变量
f1();
console.log(c);//9
console.log(b);//9
console.log(a);//报错
function f1() {
var a = b = c = 9;
console.log(a);//9
console.log(b);//9
console.log(c);//9
}
对象
概念
对象是一个具体的事物,万物皆对象
对象由属性和方法组成
属性:事物的特征,名词
方法:行为,动词
创建对象的三种方式
利用字面量创建对象
1.声明对象
var 对象名 = {
属性名1: 属性值1,
属性名2: 属性值2,
属性名n: 属性值n,
方法名1: function() {代码块},
方法名n: function() {代码块}
}
1.1里面的属性和方法采取键值对的形式书写
属性名: 属性值 方法名:匿名函数
1.2.多个属性和方法之间用逗号隔开
1.3.方法冒号后面是一个匿名函数
var obj = {
myname: '张三',
age: 18,
gender: '男',
sayHi: function () {
console.log("hi~");
}
}
2.使用对象
2.1调用属性
格式:对象名.属性名 / 对象名['属性名']
console.log(obj);//{myname: '张三', age: 18, gender: '男', sayHi: ƒ}
console.log(obj.myname);//张三
console.log(obj['myname']);//张三
2.2调用方法
对象名.方法名()
obj.sayHi()//hi~
利用new Object创建对象
var 对象名 = new Object();
var obj = new Object();
追加属性和追加方法
对象名.属性名 = 属性值; 对象名.方法名 = 函数
var obj = new Object();
obj.myname = '张三丰';
obj.age = 18;
obj.gender = '男';
obj.sayHi = function () {
console.log('hi~');
}
利用 = 赋值来追加对象的属性和方法
属性和方法之间用分号隔开
属性和方法的调用同上
console.log(obj.age);//18
console.log(obj['gender']);//男
obj.sayHi()//hi~
案例:利用new Object来创建对象
var obj = new Object();
obj.myname = '鸣人';
obj.gender = '男';
obj.age = 19;
obj.skill = function () {
console.log('影分身术');
}
console.log(obj);//{myname: '鸣人', gender: '男', age: 19, skill: ƒ}
利用构造函数创建对象
概念
为什么需要构造函数来创建对象?
因为用字面量和new object方式一次只能创建一个对象,利用构造函数一次可以创建多个对象
构造函数:当我们创建多个对象,里面的属性和方法有大量相同时,可以利用函数的方法来重复这些相同的代码,我们把这个函数称为构造函数
里面封装的不是普通代码而是对象
构造函数 就是把我们对象里面一些相同的属性和方法抽象出来封装到函数里面
格式
//创建构造函数
function 构造函数名() {
this.属性 = 值;
this.方法 = function () { }
}
//调用构造函数
new 构造函数名();
构造函数名首字母大写
构造函数调用 多一个new,每new一次就创建一个对象
构造函数不需要return就可以返回结果
调用函数返回的是一个对象
构造函数里面的属性和方法必须添加this
function Star(myname, age, gender) {
this.name = myname;
this.age = age;
this.gender = gender;
}
var zs = new Star('张三', 18, '男');
console.log(typeof zs);//object
console.log(zs);//{name: '张三', age: 18, gender: '男'}
调用属性
通过赋值的变量名.构造函数里的属性名即this后面的属性名
console.log(zs.name);//张三
console.log(zs['age']);//18
只要new一次调用的构造函数 就创建一个对象
var zs = new Star('张三', 18, '男');
var ls = new Star('李四',19,'男');
var ww = new Star('王五',20,'男');
调用方法
被赋值的变量名.构造函数中的方法名(实参);
function Star(myname, age, gender) {
this.name = myname;
this.age = age;
this.gender = gender;
this.sing = function (song) {
console.log(song);
}
}
var jjy = new Star('鞠婧祎', 18, '女');
jjy.sing('恋爱告急')//恋爱告急
案例
function Hero(name,type,blood) {
this.name = name;
this.type = type;
this.blood = blood;
this.attack = function (attack) {
console.log(attack);
}
}
var lp = new Hero('廉颇','坦克',500);
console.log(lp.name);//廉颇
lp.attack('近战');//近战
var hy = new Hero('后羿','射手',300);
console.log(hy.name);//后羿
lp.attack('远程');//远程
构造函数与对象的关系
构造函数类似于Java中的类(class),泛指有相同特征的某一大类
对象是一个具体的事物
利用构造函数创建对象的过程被称为对象的实例化
构造函数相当于设计图,对象是根据设计图创建出来的实物
构造函数创建对象的过程是从虚到实的过程
new关键字
new 构造函数可以在内存中创建一个空对象
this 会指向刚才创建的空对象
执行构造函数里面的代码,给这个空对象添加属性和方法
返回这个对象(所以无需return返回对象)
遍历对象
for in遍历对象
格式:for (var变量 in 对象)
k获取的是属性名,obj[k]获取属性值,其中k不能用''引起来
区分变量和属性名,k是变量不是属性名,所以不用''引起来
var obj = {
name: 'dick',
age: 18,
gender: 'male'
}
for (var k in obj) {
console.log(k);//name age gender (wrap)
console.log(obj[k]);// dick 18 male (wrap)
}
fo in 也可以遍历数组但是不推荐
var arr = [1,2,3,6,8]
for (var k in arr) {
console.log(arr[k]);
}
内置对象
概念
JavaScript中的对象分为3种:自定义对象(我们new出来的对象)、内置对象、浏览器对象
内置对象就是指JS语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能 (属性和方法)。直接使用,无需了解对象内具体的代码。
Math对象/数学对象
Math是一个内置对象,不是构造函数,所以无需new来调用
属性
Math.PI
console.log(Math.PI);//3.141592653589793
方法
Math.max() 获取最大值
console.log(Math.max(1,10));//10
Math.min() 获取最小值
console.log(Math.min(1,10));//1
案例:封装自己的数学对象
var myMath = {
PI: 3.1515926,
max: function () {
var max = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (max < arguments[i]) {
max = arguments[i]
}
}
return max;
},
min: function () {
var min = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (min > arguments[i]) {
min = arguments[i]
}
}
return min;
}
}
console.log(myMath.PI);//3.1515926
console.log(myMath.max(1,5,90));//90
console.log(myMath.min(1,5,90));//1
Math.abs(); 获取绝对值,含隐式转换
![](https://i-blog.csdnimg.cn/blog_migrate/cc8c4b16c0020bf7df2114bd3eab6acd.png)
console.log(Math.floor(1.9));//1
console.log(Math.ceil(1.1));//2
console.log(Math.round(1.5));//2
console.log(Math.round(1.4));//1
Math.random() 生成随机小数[0,1) 左闭右开
//随机生成[min,max]的整数
Math.floor(Math.random() * (max - min + 1)) + min;
//利用函数,封装随机生成[min,max]的整数
function getRandom(min,max) {
var random = Math.floor(Math.random() * (max - min + 1)) + min;
return random
}
console.log(getRandom(0,10));
Date对象/日期对象
Date() 日期对象是一个构造函数,必须使用new来调用创建我们的日期对象
可以理解 var arr = new Array();来创建数组对象,因为数组对象也是一个构造函数
var obj = new Object(); 来创建对象,对象也是一个构造函数
new Date();
new Date(value);
new Date(dateString);
new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]]);
中括号表示可选
monthIndex表示月份的整数值,从 0(1 月)到 11(12 月)。so,当我们想获得某月时记得-1。
date表示一个月中的第几天的整数值,从 1 开始。默认值为 1
1.使用Date
var date = Date();
var date = new Date();
console.log(date);//Thu Feb 16 2023 23:53:12 GMT+0800 (中国标准时间)
若没有参数,返回系统的当前时间
2.常用参数写法
数字型 2023, 2, 16 or字符串型'2023-2-6 08:00:01'
var date = new Date(2023, 2, 16);
console.log(date);//Thu Mar 16 2023 00:00:00 GMT+0800 (中国标准时间)
var date = new Date('2023-2-6 08:00:01');
console.log(date);//Mon Feb 06 2023 08:00:01 GMT+0800 (中国标准时间)
日期格式化
![](https://i-blog.csdnimg.cn/blog_migrate/0308ebbca2ca3354d5177322df4e77d2.png)
console.log(date.getFullYear());//无参,返回当前的年份,数字型 //2023
console.log(date.getMonth() + 1);//返回当前月份索引[0,11]-->[1,12],so+1//2
console.log(date.getDate());//返回当前日期//17
console.log(date.getDay());//返回当前周几//5 周日返回0
console.log(date.getHours());//返回当前小时//11
console.log(date.getMinutes());//返回当前分钟//21
console.log(date.getSeconds());//返回当前秒//3
案例:封装一个函数,返回当前时间,格式符合中国计时格式:年 月 日 星期 00:00:00
function getNow() {
var now = new Date();
var year = now.getFullYear();
var month = now.getMonth() + 1;
if (month < 10) {
month = "0" + month
}
var date = now.getDate();
if (date < 10) {
date = "0" + date
}
var day = now.getDay();
var hours = now.getHours();
if (hours < 10) {
hours = "0" + hours
}
var minutes = now.getMinutes();
if (minutes < 10) {
minutes = "0" + minutes
}
var seconds = now.getSeconds();
if (seconds < 10) {
seconds = "0" + seconds
}
var weekday = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]
return `now: ${year}年${month}月${date}日 ${weekday[day]} ${hours}:${minutes}:${seconds
}
console.log(getNow());
时间戳
1970年1月1日 00:00:00至今总的毫秒数
获取日期的总的毫秒数
valueOf() / getTime()
var now = new Date();
console.log(now.getTime());//1676606104612
console.log(now.valueOf());//1676606104612
简单写法(常用写法)
var now = +new Date();
console.log(now);//1676606224231
console.log(Date.now());//1676606348845
倒计时案例:
思路:设定的时间戳减去现在的时间戳,再把剩余的时间戳转换为显示的时间格式
![](https://i-blog.csdnimg.cn/blog_migrate/80d4abe9682e4445eb3f1cd05616f1ff.png)
function countDown(time) {
var nowTime = +new Date();//返回当前时间戳
var setTime = +new Date(time);//返回设置时间戳
var minusTime = (setTime - nowTime) / 1000;//剩余时间秒数
var day = parseInt(minusTime / 60 / 60 / 24)//天数
var hours = parseInt(minusTime / 60 / 60 % 24)//小时
var minutes = parseInt(minusTime / 60 % 60)//分钟
var seconds = parseInt(minusTime % 60)//秒
return `倒计时:${day}天${hours}时${minutes}分${seconds}秒`
}
console.log(countDown("2023-2-20 18:00:00"));
Array对象/数组对象
数组对象的创建
字面量和 new Array()
var arr = [];
var arr = new Array();
若使用new关键字创建数组对象,只传一个自然数表示传递的是数组对象的长度,若为其他数字类型表示无效的数组长度,会报错
var arr = new Array(2);
console.log(arr);//[空属性 × 2]
若使用new关键字创建数组对象,传递多个实参或一个非数值类型表示传递数组元素
var arr = new Array("2");
console.log(arr);//["2"]
var arr = new Array("HELLO",null,false);
console.log(arr);//['HELLO', null, false]
检测是否为数组
instanceof ,返回值是布尔类型,可用于检测是否为数组
var arr = [];
var str = "hello"
console.log(arr instanceof Array);//true
console.log(str instanceof Array);//false
Array.isArray(参数)
var arr = [];
var str = "hello"
console.log(Array.isArray(arr));//true
console.log(Array.isArray(str));//false
常用数组对象方法
数组元素增删查改的数组对象方法
添加数组元素的数组对象方法
push(参数1,参数2,参数3,...) 在数组尾部添加元素
参数为添加的元素,返回值是新增数组长度,影响原数组
var arr = [1,2,3]
console.log(arr.push(4,5,6));//6,返回的是新数组的长度
console.log(arr);//[1, 2, 3, 4, 5, 6]
unshift(elrment1,element2,element3,...)在数组头部添加元素
参数为添加的元素,返回值是新增数组长度,影响原数组
var arr = [1,2,3]
console.log(arr.unshift(4,5,6));//6,返回的是新数组的长度
console.log(arr);//[4, 5, 6, 1, 2, 3]
删除数组元素的数组对象方法
pop();删除尾部元素,不能带参数,一次只能删除一个元素,返回值是被删除的元素,影响原数组
var arr = [1,2,3]
console.log(arr.pop());//3,删除哪个元素返回哪个元素
console.log(arr);//[1, 2]
shift();删除头部元素,不能带参数,一次只能删除一个元素,返回值是被删除的元素,影响原数组
var arr = [1,2,3]
console.log(arr.shift());//1,删除哪个元素返回哪个元素
console.log(arr);//[2, 3]
案例:筛选数组
var arr = [1500, 2000, 500, 3000, 1200, 666, 1880]
//筛选出小于2000的元素
newArr = []
for (var i = 0; i < arr.length; i++) {
if (arr[i] < 2000) {
newArr.push(arr[i])
}
}
console.log(newArr);//[1500, 500, 1200, 666, 1880]
splice()数组对象方法
splice(从哪个索引开始,删除元素的个数,添加元素1,添加元素2,...)
第一个和第二个是必须参数,其余都是可选参数
会影响原数组,返回值是被删除元素组成的新数组,若没有删除则是空数组
1.添加元素,添加新元素后,之前索引号的元素以及之后的元素都后移
var arr = [1,2,"hello",null,"boys"]
console.log(arr.splice(0,0,"添加元素"));//[]
console.log(arr);//['添加元素', 1, 2, 'hello', null, 'boys']
2.修改元素
var arr = [1,2,"hello",null,"boys"]
console.log(arr.splice(1,2,"替换元素","替换元素2"));//[2, 'hello']
console.log(arr);//[1, '替换元素', '替换元素2', null, 'boys']
3.删除元素
var arr = [1, 2, "hello", null, "boys"]
console.log(arr.splice(3, 2,));//[null, 'boys']
console.log(arr);//[1, 2, 'hello']
截取数组的数组对象方法
slice(开始截取的索引号,结束截取的索引号),左闭右开[start-index,end-index)
返回值是被截取的新数组,不影响原数组
var arr = [1, 2, "hello", null, "boys"]
console.log(arr.slice(0,2));//[1, 2],截取元素左闭右开,返回被截取的元素
console.log(arr);//[1, 2, 'hello', null, 'boys']不影响原数组
无参默认截取所有元素,不影响原数组,返回原数组
console.log(arr.slice());//[1, 2, 'hello', null, 'boys']
合并数组的数组对象方法
concat(参数1,参数2,...) 方法用于合并两个或多个数组。
此方法不会更改现有数组,而是返回一个新数组。
var arr1 = ["hello", "boys"]
var arr2 = ['and', 'girls']
var arr3 = arr1.concat(arr2)
console.log(arr3);//['hello', 'boys', 'and', 'girls']
console.log(arr1);//['hello', 'boys']
var arr4 = arr2.concat(arr1)
console.log(arr4);//['and', 'girls', 'hello', 'boys']
参数不只是数组,还可以是各种数据类型的元素
var arr1 = ["hello", "boys"]
var arr2 = ['and', 'girls']
var arr3 = arr1.concat("and")
console.log(arr3);//['hello', 'boys', 'and']
var arr4 = arr1.concat("and", 'girls')
console.log(arr4);//['hello', 'boys', 'and', 'girls']
数组排序的数组对象方法
翻转数组
reverse();不带参数,影响原数组,返回值是被翻转后的数组
var arr = [22,'hello',null]
console.log(arr.reverse());//[null, 'hello', 22]
console.log(arr);//[null, 'hello', 22]
冒泡排序
sort(function(a,b){return a-b}) 升序排序
var arr = [3, 5, 7, 9, 2]
arr.sort(function (a, b) {
return a - b
})
console.log(arr);//[2, 3, 5, 7, 9]
sort(function(a,b){return b-a}) 降序排序
var arr = [3, 5, 7, 9, 2]
arr.sort(function (a, b) {
return b - a
})
console.log(arr);//[9, 7, 5, 3, 2]
查找数组索引的数组对象方法
查找数组元素的索引
![](https://i-blog.csdnimg.cn/blog_migrate/b15c38d4dd6b6d9a4537ac878b0ba3d0.png)
indexOf(元素) ,输入要查找的元素,从数组头部开始查找,返回元素首次出现的索引号,若数组中没有该元素则返回-1
var arr = [3, 5, 7, 9, 2]
console.log(arr.indexOf(5));//1,索引1
var arr = ['blue','red','red']
console.log(arr.indexOf('red'));//1
console.log(arr.indexOf('green'));//-1
lastIndexOf(元素),输入要查找的元素,从数组尾部开始往前查找返回元素首次出现的索引号,若数组中没有该元素则返回-1
var arr = ['blue','red','red']
console.log(arr.lastIndexOf('red'));//2
console.log(arr.indexOf());//-1
数组去重案例
思路:把旧数组里面不重复的元素取出来放到新数组中,重复的元素只保留一个,放到新数组中去重
遍历旧数组,用旧书组元素查询新数组元素,没有添加,有则不添加
如何得知该元素有没有存在?利用新数组.indexOf(数组元素),若返回-1,则说明新数组没有该元素
function unique(arr) {
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i]) === -1) {
newArr.push(arr[i])
}
}
return newArr
}
var demo = unique(['a', 'c', 'a', 'b', 'd', 'b', 'e', 'a', 'f'])
console.log(demo);//['a', 'c', 'b', 'd', 'e', 'f']
数组转换为字符串的数组对象方法
toString();无参,转换的字符串带有分隔符(逗号)
var arr = [1,2,3]
console.log(arr.toString());//1,2,3 转换的字符串带有分隔符(逗号)
join(分隔符),可以修改分隔符,join('')表示去除分隔符 无参默认分隔符为逗号
var arr = [1,2,3]
console.log(arr.join(""));//123
console.log(arr.join("$"));//1$2$3
console.log(arr.join());//1,2,3 无参默认分隔符为逗号
String对象/字符串对象
思考如下代码,为什么基本数据类型的字符串会有长度length属性?
对象才有属性和方法/复杂数据类型才有属性和方法
var str = 'hello';
console.log(str.length);//5
基本包装类型
基本包装类型:把简单数据类型包装为复杂数据类
为了便于操作基本数据类型,ECMAScript提供了一些特殊的引用类型:比如Boolean、
Number和String等。这样,基本数据类型就有了属性和方法。
第一步:把简单数据类型包装为复杂数据类型
var temp = new String("hello");
第二步:把临时变量的值赋值给 str
var str = temp
第三步:销毁这个临时变量
temp = null
字符串的不可变
指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中开辟了一个新的空间,原空间并不会被销毁。所以每重新赋一次值就新开辟一个空间,原空间并不会被销毁,容易造成浏览器卡顿
var str = 'andy';
console.log(str);//andy
str = 'red';
console.log(str);//red
![](https://i-blog.csdnimg.cn/blog_migrate/991453c86d4aa689af1d3d76af2ef578.png)
根据字符返回位置的字符串方法
indexOf(要查找的元素,从哪个索引号开始查找),返回首次出现要查找的元素的索引号
var str = '改革春风吹满地,春天来了';
console.log(str.indexOf('春'));//2
console.log(str.indexOf('春',4));//8
案例:查找所有o出现的位置以及次数
var str = 'obafuawjoyahjofwioawf'
var index = str.indexOf('o');
var num = 0;
while (index !== -1) {
console.log(index);//0 8 13 17 (wrap)
num++;
index = str.indexOf('o', index + 1)
}
console.log(`o出现的次数:${num}`);//4
var str = ['red', 'blue', 'red', 'green', 'pink', 'red']
var index = str.indexOf('red')
var num = 0;
while (index !== -1) {
console.log(index);
num++;
index = str.indexOf('red', index + 1)
}
console.log(`red出现的次数为:${num}`);
根据索引返回字符的字符串对象方法
![](https://i-blog.csdnimg.cn/blog_migrate/a8535f810c4160c0871ee433ee750ece.png)
charAt(index) 根据索引返回字符
var str = 'ydfagfba'
console.log(str[1]);//d
console.log(str.charAt(2));//f
charCodeAt(index) 返回相应索引号的ASCII码,目的:判断用户按下哪一个键
console.log(str.charCodeAt(0));//121
案例:求字符串中出现最多的字符,并统计其次数(难点)
var str = 'dayhhgawfuiaofjhbw'
//1.利用charAt()遍历这个字符串
//2.把每个字符都存储给对象,若没有该属性则添加,若有则加1
//3.遍历对象,得到最大值和该字符
var obj = {}
for (var i = 0; i < str.length; i++) {
var chars = str.charAt(i)
if (obj[chars]) {
obj[chars]++;
} else {
obj[chars] = 1;
}
}
var max = 0;
var ch = "";
for (var k in obj) {
if (obj[k] > max) {
max = obj[k];
ch = k;
}
}
console.log(max);
console.log(`出现次数最多的字符是${ch}`);
操作字符串的字符串对象方法
concat(str1,str2,...),用于连接两个或多个字符串拼接
var str = 'zhangsan'
console.log(str.concat(" and lisi"));//zhangsan and lisi
截取字符串
substr(start-index,length),从start索引开始,length表示截取长度
返回要截取的字符串,不影响原字符串
var str = 'zhangsan'
console.log(str.substr(1,5));//hangs
console.log(str);//zhangsan
slice(start-index,end-index),从start索引开始,到end索引结束,左闭右开,同数组,不影响原字符串
var str = 'zhangsan'
console.log(str.slice(1,2));//h
console.log(str);//zhangsan
substring(start-index,end-index),从start索引开始,到end索引结束,左闭右开,不影响原字符串
var str = 'zhangsan'
console.log(str.substring(1,3));//ha
console.log(str);//zhangsan
替换字符 replace('被替换的字符','替换为的字符')
返回被替换后的新字符串,它只会替换第一个字符
var str = '我爱你'
console.log(str.replace('我','他'));//他爱你
console.log(str);//我爱你
字符串转换为数组 split("分隔符")
类似于join("分隔符")把数组转换为字符串
var str = 'red,pink,blue,black'
console.log(str.split(","));//['red', 'pink', 'blue', 'black']
console.log(str.split());//['red,pink,blue,black'] //无参是转换为只有一个元素的数组
console.log(str);//red,pink,blue,black
转换字符串大小写
toUpperCase() 不影响原字符串
var str = 'red,pink,blue,black'
console.log(str.toUpperCase());//RED,PINK,BLUE,BLACK
toLowerCase() 不影响原字符串
var str = 'RED Hello LiLei'
console.log(str.toLowerCase());//red hello lilei
console.log(str);//RED Hello LiLei
简单数据类型与复杂数据类型
简单数据类型:在存储变量时存储的是值本身
复杂数据类型:引用数据类型,在存储时变量中存储的仅仅是地址(引用) ,因此叫做引用数据类型
通过new关键字创建的对象(系统对象、自定义对象) , 如Object. Array、 Date等
栈内存与堆内存
1、栈(操作系统) :由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;简单数据类型存放到栈里面
2、堆(操作系统) :存储复杂类型(对象) , 一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
复杂数据类型存放到堆里面
简单类型传参
函数的形参也可以看做是一个变量 ,当我们把一个值类型变量作为参数传给函数的形参时 ,其实是把变量在栈空间里的值复制了一份给形参 ,那么在方法内部对形参做任何修改,都不会影响到的外部变量。
复杂类型传参
函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一一个堆地址,所以操作的是同一一个对象。