JavaScript详细笔记2
1. JavaScript 数组
1.1 数组简介
- 概念:数组是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。
- 创建:
- 利用new创建数组
- 利用数组字面量创建数组
// 1. 数组(Array)
// 2. 利用new创建数据
var arr=new Array(); // 创建了一个空的数组
// 3. 利用数组字面量创建数组
var arr1=[]; // 创建了一个空的数组
var arr2=['xiao','美美',12,true]; // 给arr2数组进行了初始化
// 数组里面的数据一定要用逗号分隔
-
获取数组元素
-
数组的索引:索引(下标),用来访问数组元素的序号(数组元素的下标从0开始)
-
// 4. 获取数据元素 console.log(arr2); console.log(arr2[1]); // 美美
-
-
遍历数组:就是把数组的每个元素从头到尾都访问一次
// 遍历数组 var arr3=['red','green','black']; for(var i=0;i<3;i++){ console.log(arr3[i]); }
-
数组的长度 数组名.length
// 数组长度 var arr4=['刘备','关羽','张飞','马超','赵云','黄忠','姜维']; for(var i=0;i<arr4.length;i++){ console.log(arr4[i]); }
-
案例
// 案例:求一个数组里面所有元素的和以及平均值 var num=[2,6,1,7,4]; var sum=0; for(var i=0;i<num.length;i++){ sum+=num[i]; } console.log(sum); // 20 console.log(sum/num.length); // 4 // 案例2:求最大值 var arr=[2,6,1,77,52,25,7]; var max=arr[0]; for(var i=1;i<arr.length;i++){ if(arr[i]>max){ max=arr[i]; } } console.log(max); // 77 // 案例3:数组转换为分割字符串 var str=['red','green','black','pink']; var str1=''; var sep='!' for(var i=0;i<str.length;i++){ str1+=str[i]+sep; } console.log(str1); // red!green!black!pink!
-
1.2 数组中新增数组元素
-
通过修改length长度新增数组元素
var str=['red','green','black','pink']; console.log(str.length); // 4 str.length=6; // 把数组的长度修改了为6,里面有6个元素 console.log(str); // ["red", "green", "black", "pink", empty × 2]
-
修改索引号新增数组元素
var str=['red','green','black','pink']; str[4]='blue'; // 添加数组元素 console.log(str); // ["red", "green", "black", "pink", "blue"] str[0]='yellow'; // 修改数组元素 str='有点意思'; // 不要直接给数组名赋值,否则会覆盖里面的数据
-
案例:
// 新建一个数组,里面存放10个整数 var str=[]; for(var i=0;i<10;i++){ str[i]=i+1; } console.log(str); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // 案例2:筛选数组 // 方法1: var arr=[2,0,6,1,77,0,52,0,25,7]; var str1=[]; var count=0; // 计数 for(var i=0;i<arr.length;i++){ if(arr[i]>=10){ str1[count]=arr[i]; count++; } } console.log(str1); // [77, 52, 25] // 方法2: // 刚开始 str1.length 就是0 for(var i=0;i<arr.length;i++){ if(arr[i]>=10){ str1[str1.length]=arr[i]; } } console.log(str1); // [77, 52, 25]
1.3 数组案例
// 数组案例: 数组去重,删除指定数组元素
var arr=[2,0,6,1,77,52,0,25,7]; // 删除0
var str=[];
for(var i=0;i<arr.length;i++){
if(arr[i]!=0){
str[str.length]=arr[i];
}
}
console.log(str); // [2,6,1,77,52,25,7]
// 翻转数组
var arr=['red','green','blue','purple'];
var str=[];
for(var i=arr.length-1;i>=0;i--){
str[str.length]=arr[i];
}
console.log(str); // ["purple", "blue", "green", "red"]
// 数组排序(冒泡排序):按照一定的顺序进行排序显示(从小到大、从大到小)
var arr=[5,4,3,2,1];
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); // [1, 2, 3, 4, 5]
2. JavaScript 函数
2.1 函数的基础
-
概念:就是封装了一段可被重复执行的代码块,通过此代码块可以实现大量代码的重复使用。
function getSum(num1,num2){ var sum=0; for(var i=num1;i<=num2;i++){ sum+=i; } console.log(sum); } getSum(1,100); // 5050
-
函数的使用
// 声明函数 // function 函数名(){ 函数名一般是动词 // // 函数体 // } function sayHi(){ console.log('Hi~~~~'); } // 调用函数 函数不调用自己不执行 函数名() sayHi();
-
函数的参数
-
形参(函数定义时)和实参(函数调用时)
// function 函数名(形参1,形参2...){ 在声明函数的小括号里面是 形参 函数的参数可有可无,个数不限 // 函数体 // } // 函数名(实参1,实参2...); 在调用函数的小括号里面是 实参 function cook(str){ console.log(str); } cook('酸辣土豆丝'); // 酸辣土豆丝 cook('麻辣火锅鱼'); // 麻辣火锅鱼
-
-
函数形参和实参匹配问题
// 4. 函数形参和实参个数匹配 function getSum(num1,num2){ console.log(num1+num2); } // 如果实参的个数和形参的个数一致,则正常输出结果 getSum(1,2); // 3 // 如果实参的个数多于形参的个数 会取到形参的个数 getSum(1,2,3); // 3 // 如果实参的个数少于形参的个数 多的形参定义为undefined 最终的结果就是 NaN // 形参可以看做是不用声明的变量 num2 是一个变量但是没有接收值 结果就是undefined getSum(1); // NaN
-
函数的返回值
// 函数是做某件事或者实现某种功能 // 函数的返回格式 // function 函数名(){ // return 需要返回的结果; // } // 函数名(); // (1) 函数只是实现某种功能,最终的结果 需要返回给函数的调用者函数名() 通过return实现 // (2) 只要函数遇到return 就把后面的结果返回给函数的调用者 函数名()=return后面的结果 // (3) 代码验证 function getResult(){ return 666; } getResult(); // getResult() = 666 console.log(getResult()); // 666
// 案例1:利用函数求任意两个数的最大值 function getMax(num1,num2){ if(num1>num2){ return num1; }else{ return num2; } // 法二: return num1>num2?num1:num2; } console.log(getMax(3,4)); // 4 // 案例2:利用函数求任意一个数组中的最大值 function getArrMax(arr){ var max=arr[0]; for(var i=1;i<=arr.length;i++){ if(arr[i]>max){ max=arr[i]; } } return max; } // console.log(getArrMax([5,2,7,9,101,67,77,99])); // 101 实参是送一个数组过去 var re=getArrMax([5,2,7,9,101,67,77,99]); console.log(re); // 101
-
函数返回值注意事项
// 1. return终止函数 function getSum(num1,num2){ return num1+num2; // return后面的代码不会被执行 alert('我是不会被执行的哦!'); } console.log(getSum(1,2)); // 3 // 2. return只能返回一个值 function fn(num1,num2){ return num1,num2; // 返回的结果是最后一个值 } console.log(fn(1,2)); // 2 // 3. 求任意两个数的加减乘除 function getResult(num1,num2){ return [num1+num2,num1-num2,num1*num2,num1/num2]; } console.log(getResult(10,2)); // [12, 8, 20, 5] 返回的是一个数组 // 4. 函数如果有return,则返回的是return后面的值,如果函数没有return,则返回undefined function fun1(){ return 666; } console.log(fun1()); // 666 function fun2(){ } console.log(fun2()); // undefined
2.2 arguments使用
在JavaScript中,arguments实际上它是当前函数的一个内置对象,所有的函数都内置了一个arguments对象,arguments对象中存储了传递的左右实参。
// 7. arguments使用,只有函数才有
function fn(){
console.log(arguments); // 里面存储了所有传递过来的实参
console.log(arguments.length); // 3
console.log(arguments[2]); // 3
// 可以按照数组的方式遍历arguments
for(var i=0;i<arguments.length;i++){
console.log(arguments[i]);
}
}
fn(1,2,3);
arguments展示形式是一个伪数组,因此可以进行遍历,伪数组具有以下特点:
- 具有length属性
- 按索引方式存储数据
- 不具有数组的posh、pop等方法
2.3 数组案例
// 案例1:利用函数翻转数组
function reverse(arr){
var str=[];
for(var i=arr.length-1;i>=0;i--){
str[str.length]=arr[i];
}
return str;
}
var res=reverse([2,3,6,8,5,1]);
console.log(res);
// 案例2:函数封装冒泡排序
function sort(arr){
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;
}
}
}
return arr;
}
var str=sort([2,4,1,0,7,9]);
console.log(str);
// 案例3:判断闰年
function isRunYear(year){
// 如果是闰年,返回true,否则返回false
var flag=false;
if(year%4==0 && year%100!=0 || year%400==0){
flag=true;
}
return flag;
}
console.log(isRunYear(2000)); // true
console.log(isRunYear(1999)); // false
// 案例4:函数可以调用另一个函数
function fn1(){
console.log(111);
fn2();
}
fn1();
function fn2(){
console.log(222);
}
// 案例5:用户输入年份,输出当前年份2月份的天数
function backDay(){
var year=prompt('请你输入年份:');
var flag=isRunYear(year);
if(flag==true){
return 29;
}else{
return 28;
}
}
console.log(backDay());
2.4 函数声明方式
-
利用函数关键字自定义函数(命名函数)
-
函数表达式(匿名函数):声明方式与变量声明差不多,只不过变量里面存的是值,函数表达是存的是函数
// var 变量=function(){}; var fun=function(aru){ // fun是变量名 console.log('我是函数表达式'); console.log(aru); } fun('zhiyu'); // 也可进行传递参数
3. JavaScript 作用域
3.1 作用域
3.1.1 什么是作用域
- 概述:通常来说 ,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。(就是代码名字(变量)在某个范围内起作用和效果)
- 目的:提高程序的可靠性,更重要的是减少命名冲突
3.1.2 作用域分类(es6之前)
- 全局作用域:整个script标签或者是一个单独的js文件。
- 局部作用域:在函数内部就是局部作用域,这个代码的名字只在函数内部起效果和作用。(函数作用域)
3.2 变量的作用域
3.2.1 分类
- 全局变量:在全局作用域下的变量。(注意:在函数内部没有声明直接赋值的变量也属于全局变量 )
- 局部变量:在局部作用域下的变量或者在函数内部的变量。(只能在函数内部使用)(注意:函数的形参也可以看做是局部变量)
3.2.2 区别
- 全局变量只有浏览器关闭的时候才会销毁,比较占内存资源
- 局部变量:当程序执行完毕就会销毁,比较节约内存资源
JavaScript没有块级作用域 {}
3.3 作用域链
-
只要是代码,就至少有一个作用域
-
写在函数内部的是局部作用域
-
如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
-
根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作用域链(就近原则)。
var num=10; function fn(){ // 外部函数 var num=20; function fun(){ // 内部函数 console.log(num); // 20 } fun(); } fn();
案例:
// 案例一:结果是几? function f1(){ // 外部函数 var num=123; function f2(){ // 内部函数 var num=0; console.log(num); // 0 站在目标出发,一层一层的往外查找,就近原则 } f2(); } var num=456; f1(); // 案例二:结果是几? var a=1; function fn1(){ var a=2; var b='22'; fn2(); function fn2(){ var a=3; fn3(); function fn3(){ var a=4; console.log(a); // 4 console.log(b); // 22 } } } fn1();
4. JavaScript 预解析
4.1 预解析基础
4.1.1 什么是预解析
js引擎运行js分为两步:预解析和代码执行
预解析:js引擎会把js里面所有的var还有function提升到当前作用域的最前面
代码执行:按照代码书写的顺序 从上往下执行
4.1.2 预解析分类
-
变量预解析(变量提升):就是把所有的变量声明提升到当前作用域最前面,不提升赋值操作
console.log(num); // undefined var num=10; // 相当于执行了以下代码 var num; console.log(num); num=10; fun(); var fun=function(){ console.log(22); } // 相当于执行了以下代码 var fun; fun(); fun=function(){ console.log(22); }
-
函数预解析(函数提升):把所有的函数声明提升到当前作用域最前面,不调用函数
fun(); // 函数表达式调用必须写到函数下面 function fun(){ console.log(11); }
4.1.3 预解析案例
// 案例1:结果是几?
var num=10;
fun();
function fun(){
console.log(num);
var num=20
}
// 相当于执行了以下操作
var num;
function fun(){
var num;
console.log(num); // undefined
num=20
}
num=10;
fun();
// 案例2:
f1();
console.log(c); // 9
console.log(b); // 9
console.log(a); // 报错
function f1(){
var a=b=c=9; // 相当于var a=9;b=9;c=9; 集体声明 var a=9,b=9,c=9;
console.log(a); // 9
console.log(b); // 9
console.log(c); // 9
}
// 相当于执行了以下操作
function f1(){
var a;
a=b=c=9; // b,c没有声明,当全局变量看
console.log(a); // 9
console.log(b); // 9
console.log(c); // 9
}
f1();
console.log(c); // 9
console.log(b); // 9
console.log(a); // 报错
5. JavaScript 对象
5.1 对象基础
5.1.1 对象是什么?
-
现实中:对象是一个具体的事物,看得见摸得着的实物。
-
在js中:对象时一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数组、函数等。
-
对象是由属性和方法组成
- 属性:事物的特征,常用名词
- 方法:事物的行为,常用动词
5.1.2 为什么需要对象?
js中的对象表达结构更清晰、更强大
5.2 创建对象的三种方式
5.2.1 利用字面量创建对象
-
对象字面量:就是花括号{}里面包含了表达这个具体事物(对象)的属性和方法
-
里面的属性和方法采用键值对的形式 键 属性名 :值 属性值
-
多个属性或者方法中间用逗号隔开
-
方法冒号后面跟的是一个匿名函数
var obj={}; // 创建了一个空的对象
var obj1={
uname:'张三丰',
age:18,
sex:'男',
sayHi:function(){
console.log("Hi~");
}
}
// 调用对象的属性 采取(1) 对象名.属性名
console.log(obj1.sex);
// (2) 对象名['属性名']
console.log(obj1['age']);
// (3) 调用对象的方法 sayHi 对象名.方法名
obj1.sayHi(); // 千万别忘记添加小括号
变量、属性、函数、方法的区别
// 变量和属性的相同点:都是用来存储数据的
var num=10;
var obj={
age:18,
fn:function(){
}
}
function fn(){
}
console.log(obj.age);
// 变量 单独声明并赋值,使用的时候直接写变量名,单独存在
// 属性 在对象里面的不需要声明的,使用的时候必须是 对象.属性
// 函数和方法的相同点:都是实现某种功能 简单就是做某件事
// 函数是单独声明 并且调用的 函数名() 单独存在的
// 方法 在对象里面 调用的时候 对象.方法()
5.2.2 利用new Object创建对象
var obj=new Object(); // 创建了一个空的对象
obj.uname='张三丰';
obj.age=18;
obj.sex='男';
obj.sayHi=function(){
console.log("Hi~");
}
// (1) 是利用等号=赋值的方法,添加对象的属性和方法
// (2) 每个属性和方法之间用分好结束
// 调用
console.log(obj.uname);
console.log(obj.sex);
obj.sayHi();
5.2.3 利用构造函数创建对象
-
为什么需要构造函数
- 因为前面两种创建对象的方式一次只能创建一个对象,
- 里面很多的属性和方法是大量相同的,我们只能赋值,可以 利用函数的方法,重复这些相同的代码,把这些函数称之为构造函数
- 这个函数里面封装的不是普通代码,而是对象
- 构造函数:就是把我们对象里面一些相同的属性和方法抽象出来封装到函数里面
-
创建模板
function 构造函数名(){ this.属性=值; this.方法=function(){ } } new 构造函数名(); // 调用
-
案例:
// 我们创建四大天王对象 // 相同的属性:名字、年龄、性别 相同的方法:唱歌 function Star(uname,age,sex){ this.name=uname; this.age=age; this.sex=sex; this.sing=function(song){ console.log(song); } } var ldh=new Star('刘德华',18,'男'); console.log(typeof ldh); // object console.log(ldh.name); // 刘德华 ldh.sing('冰雨') // 冰雨
注意:
- 构造函数名字首字母要大写
- 构造函数不需要return就可以返回结果
- 调用函数返回的是一个对象
- 调用函数对象必须使用new
- 只要new Star() 调用函数就创建一个对象 ldh {}
- 属性和方法前面必须添加this
-
构造函数与对象的区别
- 对象是一个具体的事物,特指某一个
- 构造函数泛指某一大类,类似java语言的类(class)
- 利用构造函数创建对象的过程相当于对象实例化
5.3 new 关键字执行过程
- new 构造函数可以在内存中创建一个空的对象
- this 就会指向刚才创建的空对象
- 执行构造函数里面的代码,给这个空对象添加属性和方法
- 返回这个对象
5.4 遍历对象
-
fo…in语句:用于对数组或者对象的属性进行循环操作
-
案例
var obj={ name:'栀虞', age:21, sex:'女', fn:function(){} } // for(变量 in 对象){ // } for(var k in obj){ console.log(k); // k是变量 输出的是属性名 console.log(obj[k]); // obj[k] 得到是里面的属性值 }
6. JavaScript 内置对象
6.1 内置对象基础
- JavaScript中的对象分为三种:自定义对象、内置对象、浏览器对象
- 前面两种对象时js基础内容,属于ECMAScript;第三个浏览器对象属于js独有的
- 内置对象:就是指js语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能(属性和方法)
- 内置对象最大的优点就是帮助我们快速开发
- JavaScript提供了多个内置对象:Math、Date、Array、String等
6.2 查文档
6.2.1 MDN
- Mozilla开发者网络(MDN)提供了有关开放网络技术(Open Web)的信息,包括HTML、CSS和万维网及HTML5应用的API。
- MDN:https://developer.mozilla.org/zh-CN/
6.2.2 如何学习对象中的方法
- 查阅该方法的功能
- 查看里面的参数的意义以及类型
- 查看返回值的意义及类型
- 通过demo进行测试
6.3 Math对象
-
Math是一个内置对象,它具有数学常数和函数的属性和方法。不是一个构造对象,所以不需要new 来调用,直接使用里面的属性和方法即可。
-
// Math数学对象 console.log(Math.PI); // 3.141592653589793 一个属性,圆周率 console.log(Math.max(4,8,99,2)); // 99 console.log(Math.max(-1,-10)); // -1 console.log(Math.max(1,99,'栀虞')); // NaN console.log(Math.max()); // -Infinity
-
案例:封装自己的数学对象
var myMath={ PI:3.141592653, max:function(){ var max=arguments[0]; for(var i=1;i<arguments.length;i++){ if(arguments[i]>max){ max=arguments[i]; } } return max; }, min:function(){ var min=arguments[0]; for(var i=1;i<arguments.length;i++){ if(arguments[i]<min){ min=arguments[i]; } } return min; } } console.log(myMath.PI); // 3.141592653 console.log(myMath.max(1,4,2,7)); // 7 console.log(myMath.min(2,3,9,0)); // 0 // 绝对值方法 console.log(Math.abs(-1)); // 1 console.log(Math.abs('-1')); // 1 隐式转换,会把字符串的-1转换为数字型 console.log(Math.abs('栀虞')); // NaN // 三个取整方法 // (1) Math.floor() 向下取整,往最小了取值 console.log(Math.floor(1.5)); // 1 // (2) Math.ceil() 往上取整,往大了取值 console.log(Math.ceil(1.1)); // 2 // (3) Math.round() 四舍五入 console.log(Math.round(1.1)); // 1 console.log(Math.round(1.5)); // 2 console.log(Math.round(-1.1)); // -1 console.log(Math.round(-1.5)); //-1 其他数字都是四舍五入,单数 .5特殊,往大了取
-
Math随机数方法
- Math.random()函数返回一个浮点,伪随机数在范围==[0,1)==,你可以缩放到所需的范围
- 没有参数
// Math.random() console.log(Math.random()); // 0.6666185018110495 // 两个数之间的随机整数,并且包括两个数在内 // Math.floor(Math.random()*(max-min+1))+min function getRandom(min,max){ return Math.floor(Math.random()*(max-min+1))+min; } console.log(getRandom(1,10)); // 10 // 案例:随机点名 var arr=['张三','李四','张三丰','李思思','王五']; console.log(arr[getRandom(0,arr.length-1 )]);
-
案例:
// 案例:猜数字游戏 function getRandom(min,max){ return Math.floor(Math.random()*(max-min+1))+min; } var num=getRandom(1,10); while(true){ // 死循环 var num1=prompt('你来猜?输入1-10之间的一个数字:'); if(num1>num){ alert('你猜大了'); }else if(num1<num){ alert('你猜小了'); }else{ alert('你猜对了'); break; // 退出整个循环结束程序 } } // 猜数字游戏,猜的次数有限制10次 function getRandom(min,max){ return Math.floor(Math.random()*(max-min+1))+min; } var num=getRandom(1,50); var count=0; for(var i=0;i<10;i++){ // 死循环 count++; var num1=prompt('你来猜?输入1-50之间的一个数字:'); if(num1>num){ alert('你猜大了'); }else if(num1<num){ alert('你猜小了'); }else{ alert('你猜对了'); break; // 退出整个循环结束程序 } if(count==3){ alert('超出猜数的次数,你失败了!') break; } }
6.4 日期对象
-
创建Date实例来处理日期和时间,Date对象基于1970年1月1日(世界标准时间)起的毫秒。
-
需要通过调用函数Date来实例化日期对象,以常规函数调用它(即不加new操作符)将会返回一个字符串,而不是一个日期对象。
-
Date() 日期对象,是一个构造函数,必须使用new来调用创建我们的日期对象。
-
// Date() 日期对象 var arr=new Array(); // 创建了一个数组对象 var obj=new Object(); // 创建了一个对象实例 // 1. 使用Date var date=new Date(); // 如果没有参数,则返回系统当前时间 console.log(date); // Tue Nov 30 2021 22:22:06 GMT+0800 (中国标准时间) // 2. 参数常用的写法 数字型 2019,10,01 字符串型 '2019-10-1 8:8:8' var date1=new Date(2019,10,01); console.log(date1); // Fri Nov 01 2019 00:00:00 GMT+0800 (中国标准时间) var date2=new Date('2019-10-1 8:8:8'); console.log(date2); // Tue Oct 01 2019 08:08:08 GMT+0800 (中国标准时间)
-
格式化日期年月日星期
var data=new Date(); console.log(data.getFullYear()); // 返回当前日期的年 2021 console.log(data.getMonth()+1); // getMonth()返回当月(0-11) 12 console.log(data.getDate()); // 返回的是几号 4 console.log(data.getDay()); // 返回的是周几 (0到周六,0表示周日) 周六 // 写一个2021年12月4日星期六 var year=data.getFullYear(); var month=data.getMonth(); var datas=data.getDate(); var arr=['星期日','星期一','星期二','星期三','星期四','星期五','星期六']; var day=arr[data.getDay()]; console.log('今天是'+year+'年'+month+'月'+datas+'日 '+day); // 今天是2021年11月4日 星期六
-
格式化日期时分秒
var date=new Date(); console.log(date.getHours()); // 返回当前的小时 15 console.log(date.getMinutes()); // 返回当前的分钟 30 console.log(date.getSeconds()); // 返回当前的秒 39 // 要求封装一个函数,返回当前的时分秒 格式08:08:08 function getTime(){ var time=new Date(); var h=time.getHours(); h=h<10?'0'+h:h; var m=time.getMinutes(); m=m<10?'0'+m:m; var s=time.getSeconds(); s=s<10?'0'+s:s; return h+':'+m+":"+s; } console.log(getTime()); // 15:35:04
-
获取日期的总的毫秒形式
// 通过Date获得总的毫秒数(时间戳),不是当前时间的毫秒数,而是距离1970年1月1日过了多少毫秒数 // 1. 通过valueOf() getTime(); var data=new Date(); console.log(data.valueOf()); // 1638603621183 console.log(data.getTime()); // 1638603621183 // 2. 简单的写法(最常用的写法) var data1=+new Date(); // +new Date() 返回的就是总毫秒数 console.log(data1); // 1638603693931 // 3. H5新增的 获得总的毫秒数 console.log(Date.now()); // 1638603758360
-
案例:倒计时效果
- 核心算法:输入的时间减去现在的时间就是剩余时间,即倒计时,但是不能拿这时分秒相减,比如05分减去25分,结果会是负数。
- 用时间戳来做。用户输入时间总的毫秒数减去现在时间总的毫秒数,得到的就是剩余时间的毫秒数
- 把剩余时间总的毫秒数转换为天、时、分、秒(时间戳转换为时分秒)
function countDown(time){
var nowTime=+new Date(); // 返回当前时间总的毫秒数
var inputTime=+new Date(time); // 返回的是用户输入时间的毫秒数
var times=(inputTime-nowTime)/1000; // times是剩余时间总的秒数
var d=parseInt(times/60/60/24); // 天
d=d<10?'0'+d:d;
var h=parseInt(times/60/60%24); // 时
h=h<10?'0'+h:h;
var m=parseInt(times/60%60); // 分
m=m<10?'0'+m:m;
var s=parseInt(times%60); // 秒
s=s<10?'0'+s:s;
return d+'天'+h+'时'+m+'分'+s+'秒';
}
console.log(countDown('2021-12-12 18:00:00')); // 08天01时46分46秒
6.5 数组对象
6.5.1 数据创建及检测是否为数组
// 创建
var arr=[1,2,3]; // 字面量
var arr1=new Array(2); // new Array(); 表示长度为2的空数组arr1
var arr2=new Array(2,3); // 等价于 var arr2=[2,3];
// 检测是否为数组
// (1) instanceof 运算符 可以用来检测是否为数组
var arr=[];
var obj={};
console.log(arr instanceof Array); // true
console.log(obj instanceof Array); // false
// (2) Array.isArray(参数) H5新增,IE9以上版本支持
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false
6.5.2 添加删除数组元素
// 1. push() 在我们数组的末尾,添加一个或者多个数组元素 push 推
var arr=[1,2,3];
// arr.push(4,'栀虞');
console.log(arr.push(4,'栀虞')); // 5 返回新数组的长度
console.log(arr); // [1, 2, 3, 4, "栀虞"]
// (1) push(unshift)是可以给数组追加新的元素
// (2) push()(unshift()) 参数直接写数组元素即可
// (3) push(unshift)完毕之后,返回的结果是新数组的长度
// (4) 原数组也会发生变化
// 2. unshift 在数组的开头,添加一个或者多个数组元素
arr.unshift('red');
console.log(arr); // ["red", 1, 2, 3, 4, "栀虞"]
// 3. pop() 可以删除数组的最后一个元素,没有参数
// arr.pop();
console.log(arr.pop()); // 栀虞 返回的是删除的那个元素
console.log(arr); // ["red", 1, 2, 3, 4]
// 4. shift() 可以删除数组的第一个元素,没有参数
console.log(arr.shift()); // red
console.log(arr); // [1, 2, 3, 4]
6.5.3 案例:筛选数组
有一个包含工资的数组[1500,1200,2000,2100,1800],要求把数组中工资超过2000的删除,剩余的放到新数组
var arr=[1500,1200,2000,2100,1800];
var newArr=[];
for(var i=0;i<arr.length;i++){
if(arr[i]<2000){
// newArr[newArr.length]=arr[i];
newArr.push(arr[i]);
}
}
console.log(newArr); // [1500, 1200, 1800]
6.5.4 数组排序
// 1. 翻转数组
var arr=['tom','red','blue'];
arr.reverse();
console.log(arr); // ["blue", "red", "tom"]
// 2. 数组排序(冒泡排序)
var arr1=[33,4,77,1,19];
arr1.sort(function(a,b){ // 只是用sort()没有函数的话只能排序个位数
return a-b; // 升序
// return b-a; // 降序
});
console.log(arr1); // [1, 4, 19, 33, 77]
6.5.5 获取数组元素索引
// indexOf(数组元素):返回该数组元素的索引号 只返回第一个满足条件的数组元素的索引号,如果数组没有这个数组元素,返回-1
var arr=['red','blue','zhiyu','green'];
console.log(arr.indexOf('blue')); // 1
// lastindexOf(数组元素):从最后面一个元素开始索引,但返回还是原来的
console.log(arr.lastIndexOf('blue')); // 1
6.5.6 数组去重案例
有一个数组[‘c’,‘a’,‘z’,‘x’,‘a’,‘x’,‘c’,‘b’],要求去除数组中的重复元素
核心原理:遍历旧数组,然后拿旧数组去查询新数组,如果该元素在新数组不存在,则添加,否则不添加
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 arr=['c','a','z','x','a','x','c','b'];
console.log(unique(arr)); // ["c", "a", "z", "x", "b"]
6.5.7 数组转换为字符串
// 1. toString() 将我们的数组转换为字符串
var arr=[1,2,3];
console.log(arr.toString()); // 1,2,3
// 2. join(分隔符)
var arr1=['green','blue','zhiyu'];
console.log(arr1.join('-')); // green-blue-zhiyu
6.6 字符串对象
6.6.1 基本包装类型
JavaScript还提供了三个特殊的应用类型:String、Number、Boolean
基本包装类型就是把简单数据类型包装成为复杂数据类型,这样基本数据类型就有了属性和方法
var str='andy';
console.log(str.length); // 4
// 对象、复杂数据类型才有属性和方法
// 基本包装数据类型:就是把简单数据类型包装成了复杂数据类型
// (1) 生成临时变量,把简单数据类型包装成复杂数据类型
var temp=new String('andy');
// (2) 把临时变量的值给str
str=temp;
// (3) 销毁这个临时变量
temp=null;
6.6.2 字符串的不可变
指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。
不要大量的拼接字符串
6.6.3 根据字符返回位置
字符串所有方法,都不会修改字符串本身(字符串是不可变的),操作完成后会返回一个新的字符串。
// 根据字符返回位置 str.indexOf('要查找的字符',[起始的位置])
var str='改革春风吹满地,春天来了';
console.log(str.indexOf('春',3)); // 8 从索引号是3的位置开始查找
console.log(str.lastIndexOf('春',3)); // 2 从倒数索引号为3的位置倒着查找
案例:返回字符位置
查找字符串"abcoefoxyozzopp"中所有o出现的位置以及次数
核心算法:先查找第一个o出现的位置,然后只要indexOf()返回的结果不是-1,就继续往下查找,因为indexOf只能查找一个,所以后面的查找就用第二个参数,当前索引加1,从而继续查找。
function strSearch(str,split){
var index=str.indexOf(split);
var num=0;
while(index!=-1){
console.log(index);
num++;
index=str.indexOf(split,index+1);
}
console.log(num);
}
var split='o';
var str="abcoefoxyozzopp";
strSearch(str,split); // 3 6 9 12 4次
6.6.4 根据位置返回字符
// 1. charAt(index) 根据位置返回字符
var str='andy';
console.log(str.charAt(3)); // y
// 遍历所有的字符
for(var i=0;i<str.length;i++){
console.log(str.charAt(i));
}
// 2. charCodeAt(index) 返回相应索引号的字符ASCII值 目的:判断用户按下了那个键
console.log(str.charCodeAt(0)); // 97
// 3. str[index] 获取指定位置字符 H5新增,IE8+支持charAt()等效
console.log(str[1]); // n
案例:统计出现次数最多的字符和次数
判断字符串"abcoefoxyozzopp"中出现次数最多的字符,并统计其次数
核心算法:利用charAt()遍历这个字符串;把每个字符都存储给对象,如果对象没有这个属性,就为1,如果存在+1;遍历对象,得到最大值和该字符。
function maxSearch(str){
var o={};
var max=0;
var ch='';
// 1. 计算每个字符出现的次数
for(var i=0;i<str.length;i++){
var chars=str.charAt(i); // chars是字符串中的每个字符
if(o[chars]){ // o[chars]得到的是属性值
o[chars]++;
}else{
o[chars]=1;
}
}
console.log(o);
// 2. 得到最大值
for(var k in o){
// k得到的是属性名,o[k]得到的是属性值
if(o[k]>max){
max=o[k];
ch=k;
}
}
console.log('出现次数最多的是:'+ch+',出现了'+max+'次');
}
var str="abcoefoxyozzopp";
maxSearch(str);
6.6.5 字符串操作方法
- concat(str1,str2,str3…):用于连接两个换货多个字符串,拼接字符串,等效于+,但+更常用。
- substr(start,length):从start开始(索引号),length取的个数。
- slice(start,end):从start位置开始,截取到end位置,end位置取不到(两个都是索引号)。
- substring(start,end):从start开始,截取到end,end取不到,基本和slice一致,但不接受负值。
var str='andy';
console.log(str.concat('red')); // andyredvar
str1='春天来了,冬天还会远吗?';
console.log(str1.substr(1,3)); // 天来了
- replace(‘被替换的字符’,‘替换为的字符’):替换字符
- split(‘分隔符’):字符转换为数组
// replace()方法
var str='andy';
console.log(str.concat('red')); // andyred
var str1='春天来了,冬天还会远吗?';
console.log(str1.substr(1,3)); // 天来了
var str2='andy';
console.log(str2.replace('a','b')); // bndy
// 有一个字符串,"abcoefoxyozzopp",要求把替换为*
var str3='abcoefoxyozzopp';
while(str3.indexOf('o')!=-1){
str3=str3.replace('o','*');
}
console.log(str3); // abc*ef*xy*zz*pp
// split()方法
var str4='red-green-blue';
console.log(str4.split('-')); // ["red", "green", "blue"]
- toUpperCase():转换大写
- toLowerCase():转换小写
7. JavaScript 简单数据类型与复杂数据类型
7.1 简单数据类型与复杂数据类型
简单类型又叫做基本数据或者值类型,复杂类型又叫应用类型
值类型:在存储时变量中存储的是值本身,因此叫做值类型–>string,number,boolean,undefined,null
应用类型:在存储时变量中存储的仅仅是地址(应用),因此叫做应用数据类型–>通过new关键字创建的对象(系统对象、自定义对象),Object、Array、Date等
堆和栈
- 栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等,其操作方式类似于数据结构中的栈;简单数据类型放到栈里面(存放在栈里面,直接开放开辟一个空间存值)
- 堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型存放到堆里面(首先在栈里面存放地址,然后这个地址指向堆里面的数据)
7.2 传参
// 简单数据类型传参
function fn(a){
a++;
console.log(a);
}
var x=10;
fn(x); // 11
console.log(x); // 10
// 复杂数据类型传参
function Person(name){
this.name=name;
}
function f1(x){
console.log(x.name); // 2 刘德华
x.name='张学友';
console.log(x.name); // 3 张学友
}
var p=new Person('刘德华');
console.log(p.name); // 1 刘德华
f1(p);
console.log(p.name); // 4 张学友