JavaScript笔记
一、js简介
1.1 js的组成
-
ECMAScript js语法
-
DOM 页面文档对象
-
BOM 浏览器对象模型
1.2 avaScript在HTML的引用方式
(1)行内式;
<input type="button" value="海贼王" onclick="alert('路飞')">
(2)内嵌式;
<script>
alert('one piece')
</script>
(3)引入外部JS文件;
<script src="my.js"></script>
alert('luffy')
二、 js基础
2.1 输入输出
1.prompt(info) 浏览器弹出输入框,用户可以输入
2.alert(msg) 浏览器弹出警示框,输出
3.console.log(msg) 浏览器控制台打印输出信息—给程序员测试用的
2.2 变量
声明变量
var:变量名;
初始化:var:变量名 = 值;
变量使用
<script>
var myname = prompt('请输入姓名');
alert(myname)
</script>
2.3 数据类型
-
数据类型是根据所赋的值来确定
-
JavaScript 拥有动态类型,同时也意味着相同的变量可变作不同的类型
数字类型可分为两类:
2.3.1. 基本数据类型(Number,String,Boolean,Undefined,Null)
简单数据类型 | 说明 | 默认值 |
---|---|---|
Number | 数字型,包含整型值和浮点型值,如21,0.21 8进制:数字前加0;16进制:前加0x |
0 |
Boolean | 布尔值类型,如true,false ,等价于1和0 | false |
Undefined | var a; 声明了变量a但是没有赋值,此时a=undefined | undefined(未定义的) |
string | 字符串类型,如“张三” | “” |
Null | var a = null;声明了变量a为空值 | null |
数字型
特殊数字型
console.log(Number.MAX_VALUE);//最大值
console.log(Number.MIN_VALUE);//最小值
console.log(Number.MAX_VALUE * 2);//无穷大
console.log(-Number.MAX_VALUE * 2);//无穷小
NaN:非数字的
isNaN()方法
这个方法用来判断非数字,并且返回一个值,如果是数字返回的是false,如果不是数字返回的是true
var userAge = 21;
var isOk = isNan(userAge);
console.log(isNum); //false,21不是一个非数字
var userName = "andy";
console.log(isNan(userName)); //true,"andy"是一个非数字
字符串型
- 1.转义字符都是以 \ 开头,只在引号内使用
转义符 | 解释说明 |
---|---|
\n | 换行符,n是newline |
\ \ | 斜杠\ |
\ ’ | ’ 单引号 |
\ ‘’ | ‘’ 双引号 |
\ t | tab 缩进 |
\ b | 空格,b是blank的意思 |
- 2.length属性
可以获取字符串长度
var myname = '请输入姓名';
console.log(myname.length);
- 3.字符串的拼接
//1 字符串相加
alert('hello' + ' ' + 'World'); //hello World
//2 数值字符串相加
alert('100' + '100'); //100100
//3 数值字符串+数值
alert('12'+12); //1212
//4 数值+数值
alert(12+12); //24
var age = 18;
console.log('我今年'+age+'岁');
- 4.typeof
typeof 可用来获取检测变量的数据类型
var num = 18;
console.log(typeof num)
2.3.2. 复杂数据类型(Object)
2.3.3 数据类型的转换
1).转换为字符串型
方式 | 说明 | 案例 |
---|---|---|
toString() | 转成字符串 | var num = 1; alert(num.toString()); |
String()强制转换 | 转成字符串 | var num = 1; alert(String(num)); |
加号拼接字符串(常用) | 和字符串拼接的结果都是字符串 | var num =1; alert(num+”); |
2).转换为数字型
方式 | 说明 | 案例 |
---|---|---|
parseInt(string)函数(常用) | 将string类型转成整数数值型 | parseInt(‘78’) |
parseFloat(string)函数(常用) | 将string类型转成浮点数数值型 | parseFloat(‘78.21’) |
Number()强制转换函数 | 将string类型转换为数值型 | Number(‘12’) |
js 隐式转换(- * /) | 利用算术运算隐式转换为数值型 | ‘12’-0 |
var age = prompt('请输入年龄');
console.log(parseInt(age));
console.log(parseFloat(age));
console.log(Number(age));
console.log(age - 0);
3).转换为布尔型
Boolean()函数
代表空、否定的值会被转换为false,如‘’,0,NaN, null, undefined, 其余会被转换为true
2.4 运算符
2.4.1 浮点数的精度问题:
浮点数值的最高精度是17位小数,但在进行算数计算时其精确度远远不如整数。所以不要直接判断两个浮点数是否相等
var result = 0.1 +0.2; //结果不是0.3,0.30000000000000004
console.log(0.07 * 100); //结果不是7,而是7.000000000000001
a++:先返回,后自加1
++a:先自加1,后返回
2.4.2 比较运算符的补充
符号 | 作用 | 用法 |
---|---|---|
== | 判断 | 判断两边值是否相等(注意此时有隐式转换) |
=== | 全等 | 判断两边的值和数据类型是否完全相同 |
2.4.3 短路运算(逻辑中断)
短路运算的原理:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值
①逻辑与
语法:表达式1 && 表达式2
如果第一个表达式的值为真,则返回表达式2
如果第一个表达式的值为假,则返回表达式1
console.log(123 && 456); //456
console.log(0 && 456); //0
console.log(123 && 456 && 789); //789
②逻辑或
语法:表达式1 || 表达式2
如果第一个表达式的值为真,则返回表达式1
如果第一个表达式的值为假,则返回表达式2
console.log(123 || 456); //123
console.log(0 || 456); //456
console.log(123 || 456 || 789); //123
var num = 0;
console.log(123 || num++);
// 先返回在加,相当于 (123 || 0)
console.log(num); // 123
2.4.4 赋值运算符
赋值运算符 | 说明 | 案例 |
---|---|---|
= | 直接赋值 | var usrName = ‘我是值’ |
+= ,-= | 加,减一个数后再赋值 | var age = 10; age+=5;//15 |
*=,/=,%= | 成,除,取模后再赋值 | var age = 2; age*=5; //10 |
2.4.5 运算符的优先级
优先级 | 运算符 | 顺序 |
---|---|---|
1 | 小括号 | () |
2 | 一元运算符 | ++ – ! |
3 | 算数运算符 | 先 * / 后 + – |
4 | 关系运算符 | >, >= , < , <=, |
5 | 相等运算符 | ,!=,=,!== |
6 | 逻辑运算符 | 先 && 后 “或”(符号打不出来) |
7 | 赋值运算符 | = |
8 | 逗号运算符 | , |
2.5 流程控制
2.5.1 选择
1) if…else 语句
2) 三元表达式
语法结构 : 条件表达式? 表达式1 : 表达式2
执行思路:如果条件表达式为 真,则 返回 表达式1;如果表达式1为 假,则 返回 表达式2
3) switch 语句
表达式的返回值与 value的值 相匹配,即选择
switch(表达式){
case value1:
执行语句1;
break;
case value2:
执行语句2;
break;
default:
执行最后的语句;
2.5.2 循环
追加字符串
var str = '';
for (var i = 0; i <= 5; i++) {
str = str + '☆';
}
console.log(str);
九九乘法表案例
var mul = 0, str = '';
for (var i = 1; i <= 9; i++) {
for (var j = 1; j <= i; j++) {
mul = i * j;
str += j + 'x' + i + '=' + mul + ' ';
}
str = str + '\n';
}
console.log(str);
2.6数组
2.6.1 创建数组
①利用 new 创建数组
var 数组名 = new Array();
var arr = new Array(); //创建一个新的空数组 注意 Array(),A要大写
②利用数组字面量创建数组
// 1.利用数组字面量方式创建空的数组
var 数组名 =[];
// 2.使用数组字面量方式创建带初始值的数组
var 数组名 =['小白','小黑','小黄','瑞奇'];
// 3.数组中可以存放任意类型的数据,例如字符串,数字,布尔值等
var arrStus =['小白',12,true,28.9];
2.6.2 遍历数组
var arr = ['red','green', 'blue'];
console.log(arr[0]) // red
console.log(arr[1]) // green
console.log(arr[2]) // blue
// for循环遍历数组
var arr = ['red','green', 'blue'];
for (var i = 0; i < arr.length; i++){
console.log(arrStus[i]);
}
2.6.3新增数组元素
①通过修改 length 长度新增数组元素
可以通过修改 length 长度来实现数组扩容的目的
length 属性是可读写的,自动检测数组长度的变化
var arr = ['red', 'green', 'blue', 'pink'];
arr.length = 7;
console.log(arr);
console.log(arr[4]);
console.log(arr[5]);
console.log(arr[6]);
其中索引号是 4,5,6 的空间没有给值,就是声明变量未给值,默认值就是 undefined
②通过修改数组索引新增数组元素
可以通过修改数组索引的方式追加数组元素
不能直接给数组名赋值,否则会覆盖掉以前的数据
这种方式也是我们最常用的一种方式
var arr = ['red', 'green', 'blue', 'pink'];
arr[4] = 'hotpink';
console.log(arr);
将一个数组中的元素放到另一个数组
- 第一种方法
var arr = [2, 0, 17, 15, 4, 8, 16, 3, 10, 7];
var a1 = [];
var j = 0;
for (i = 0; i <= arr.length; i++) {
if (arr[i] >= 7) {
a1[j] = arr[i];
j++;
}
}
console.log(a1);
- 第二种方法:使用length属性
var arr = [2, 0, 17, 15, 4, 8, 16, 3, 10, 7];
var a1 = [];
for (i = 0; i <= arr.length; i++) {
if (arr[i] >= 7) {
a1[a1.length] = arr[i];
}
}
console.log(a1);
2.6.4 冒泡排序法
var a = [2, 0, 17, 15, 4, 8, 16, 3, 10, 7];
for (var j = 0; j <= a.length - 1; j++) {
// 重复选最大的值,即选出第二大、第三大...的值,直到所有值都排列完
for (var i = 0; i <= a.length - 1; i++) {
// 选出最大的值放到最后
// a.length - i - 1是指后面的排好序就不再比较
if (a[i] >= a[i + 1]) {
var c = 0;
c = a[i];
a[i] = a[i + 1];
a[i + 1] = c;
}
}
}
console.log(a);
2.7 函数
2.7.1 函数使用
- 声明函数:function:函数名(参数){函数体}
(参数可不写)
注:函数名一般是动词
function a(num1, num2) {
var sum = 0;
for (var i = num1; i <= num2; i++) {
sum = sum + i;
}
return sum;
}
- 调用函数:
console.log(a(1, 5));//a(1,5)为调用格式
实参个数等于形参个数:输出正确结果
实参个数多于形参个数:只取到形参的个数
实参个数小于形参个数:多的形参定义为undefined,结果为NaN
ruturn只返回最后一个值。
2.7.2 arguments的使用
当我们不确定有多少个参数传递的时候,可以用 arguments 来获取。在 JavaScript 中,arguments 实际上它是当前函数的一个内置对象。所有函数都内置了一个 arguments 对象,arguments 对象中存储了传递的所有实参。
-
arguments存放的是传递过来的实参
-
arguments展示形式是一个伪数组,因此可以进行遍历。伪数组具有以下特点:
①具有 length 属性 ②按索引方式储存数据 ③不具有数组的 push() , pop() 等方法
function fn() {
console.log(arguments); //里面存储了所有传递过来的实参
console.log(arrguments.length); // 3
console.log(arrguments[2]); // 3
}
fn(1,2,3);
翻转数组
- 用arguments实现
function reverse() {
var a1 = [];
for (i = arguments.length - 1; i >= 0; i--) {
a1[a1.length] = arguments[i];
}
return a1;
}
console.log(reverse(1, 2, 8, 3, 4, 9, 7, 5, 6));
- 用数组实现
function reverse(arr) {
var a1 = [];
for (i = arr.length - 1; i >= 0; i--) {
a1[a1.length] = arr[i];
}
return a1;
}
console.log(reverse([1, 2, 8, 3, 4, 9, 7, 5, 6]));
2.7.3 函数表达式方式(匿名函数)
利用函数表达式方式的写法如下:
// 这是函数表达式写法,匿名函数后面跟分号结束
var fn = function(){...};
// 调用的方式,函数调用必须写到函数体下面
fn();
- 因为函数没有名字,所以也称为匿名函数
- 这个fn 里面存储的是一个函数
- 函数调用的代码必须写到函数体后面
- 函数表达式也可以进行传参
2.8 作用域
一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
JavaScript (ES6前) 中的作用域有两种:全局作用域和局部作用域(函数作用域)
-
全局作用域:作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件
-
局部作用域:作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域
-
JS 没有块级作用域:块作用域由 {} 包括;在其他编程语言中(如 java、c#等),在 if 语句、循环语句中创建的变量,仅仅只能在本 if 语句、本循环语句中使(js是在es6的时候新增的块级作用域),
2.8.1 变量的作用域
在JavaScript中,根据作用域的不同,变量可以分为两种:全局变量和局部变量
1)全局变量:
在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存
注意:在函数内部没有声明的变量,也属于全局变量
2)局部变量:
只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间
注意:函数的形参也属于局部变量
根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
2.8.2作用域链:
采取就近原则的方式来查找变量最终的值。
// 作用域链: 内部函数访问外部函数的变量,采取的是链式查找的方式来决定取哪个值,这种结构我们称为作用域链表
var num = 10;
function fn() {//外部函数
var num = 20;
function fun() {//内部函数
console.log(num);
}
fun();
}
fn(); //20
2.9 预解析
JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的。JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行。
1. 预解析:js引擎会把js里面所有的 var(变量声明) 还有 function(函数声明) 提升到当前作用域的最前面,但不会提升赋值,也不调用函数。
2. 代码执行:从上到下执行JS语句
练习1:
var num = 10;
fun();
function fun() {
console.log(num); //undefined
var num = 20;
}
// 最终结果是 undefined
上述代码相当于执行了以下操作
var num;
function fun() {
var num;
console.log(num);//这里是根据就近原则,输出上面的新定义的num
num = 20;
}
num = 10;
fun();
练习4
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
var a = b = c = 9;
// 相当于 var a = 9; b = 9;c = 9; b和c的前面没有var声明,当全局变量看
// 集体声明 var a = 9,b = 9,c = 9;
console.log(a);
console.log(b);
console.log(c);
}
上述代码相当于执行了以下操作
function f1() {
var a;
a = b = c = 9;
console.log(a); //9
console.log(b); //9
console.log(c); //9
}
f1();
console.log(c); //9
console.log(b); //9
console.log(a); //报错 a是局部变量
2.10 对象
在 JavaScript 中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。
对象是由属性和方法组成的:
- 属性:事物的特征,在对象中用属性来表示(常用名词)
- 方法:事物的行为,在对象中用方法来表示(常用动词)
变量、属性、函数和方法的区别
- 变量和属性都是用来存储数据的
1.1 变量 单独声明并赋值,使用的时候直接写变量名,单独存在
1.2 属性 在对象里面的不需要声明的,使用的时候必须是 对象.属性 - 函数和方法都是实现某种功能,做某件事
2.1 函数是单独声明,并且调用的函数名()单独存在的
2.2 方法,在对象里面,调用的时候,对象.方法()
2.10.1 创建对象
在 JavaScript 中,现阶段我们可以采用三种方式创建对象(object):
-
利用字面量创建对象;
-
利用 new Object创建对象;
-
利用构造函数创建对象
1)利用字面量创建对象
对象字面量:就是花括号{}里面包含了表达这个具体事物(对象)的属性和方法
var obj = {
uname: '木头蛋卷',//多个属性值或方法之间要用逗号隔开
age: 22,
sex: '女',
sayhi: function () {//方法冒号后面跟的是一个匿名函数
console.log("hi~");
}
}
使用对象
- 对象里面的属性调用 : 对象.属性名
console.log(obj.age, obj.uname, obj.sex);
- 对象里面属性的另一种调用方式 : 对象[‘属性名’],注意方括号里面的属性必须加引号
console.log(obj['uname']);
- 对象里面的方法调用:对象.方法名() ,注意这个方法名字后面一定加括号
obj.sayhi();
2) 利用 new Object 创建对象
-
跟之前的 new Array() 原理一致:var 对象名 = new Object();
-
使用的格式:对象.属性 = 值
var obj = new Object(); //先创建了一个空的对象
obj.name = '张三丰';//每个属性和方法之间用分号结束
obj.age = 18;
obj.sex = '男';
obj.sayHi = function() {
console.log('hi~');
}
//利用等号赋值的方法添加对象
console.log(obj.uname);
console.log(obj['sex']);
obj.sayHi();
3)利用构造函数创建对象
构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 运算符一起使用。
我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
在 js 中,使用构造函数要时要注意以下两点:
-
构造函数用于创建某一类对象,其首字母要大写
-
构造函数要和 new 一起使用才有意义
-
构造函数不需要return,就可以返回结果
构造函数的语法格式
function 构造函数名() {
this.属性 = 值;
this.方法 = function() {}
}
使用构造函数
new 构造函数名();
例:
function Story(t, pl, pe) {//形参
this.time=t;//实参传给形参,形参再赋值给属性
this.placce=pl;
this.people=pe;
this.dream = function (want) {
console.log('他要' + want);
}
}
var onePiece = new Story('某一年', '东海的小岛上', '王路飞');//实参
console.log(onePiece.time + '在' + onePiece.placce + '有个叫' + onePiece.people + '的人发生的的事');//某一年在东海的小岛上有个叫王路飞的人发生的的事
onePiece.dream('成为海贼王');//他想要成为海贼王
//注意格式
-
构造函数,如 Stars(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类(类似于java中的类class)
-
通过 new 关键字创建对象的过程我们也称为对象实例化
new 在执行时会做四件事:
-
在内存中创建一个新的空对象。
-
让 this 指向这个新的对象。
-
执行构造函数里面的代码,给这个新对象添加属性和方法
-
返回这个新对象(所以构造函数里面不需要return)
2.10.2 遍历对象的属性
for…in 语句用于对数组或者对象的属性进行循环操作
语法如下:
for(变量 in 对象名字){
// 在此执行代码
}
语法中的变量是自定义的,它需要符合命名规范,通常我们会将这个变量写为 k 或者 key。
for(var k in obj) {
console.log(k); //这里的 k 是属性名
console.log(obj[k]);//这里的 obj[k] 是属性值
}
2.11 内置对象
JavaScript 中的对象分为3种:
自定义对象 、内置对象、 浏览器对象
- 内置对象就是指 JS 语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能
2.11.1 Math对象
Math数学对象,不是一个构造函数,所以我们不需要new 来调用,而是直接使用里面的属性和方法即可
console.log(Math.PI);//一个属性 圆周率
console.log(Math.max(1, 5, 3));
常用的Math方法:
Math.PI // 圆周率
Math.floor() // 向下取整
Math.ceil() // 向上取整
Math.round() // 四舍五入版 就近取整 注意 -3.5 结果是 -3
Math.abs() // 绝对值 能隐式转换
Math.max()/Math.min() // 求最大和最小值
-
random 随机数方法
Math.random() 函数返回一个浮点数, 伪随机数在范围从0 到小于1
console.log(Math.random());//随机值为一个小数
想要得到两个数之间的随机数
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
console.log(getRandomArbitrary(1, 10));//随机生成数 1<= x <=10
得到两个数之间的随机整数
function getRandomIntInclusive(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值
}
案例:
//猜数
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值
}
var num = getRandom(1, 10);
while (true) {//条件为true是死循环
var grass = prompt('请输入您猜的数(范围为1~10)');
if (num < grass) {
alert('您猜的数太大了');
} else if (num > grass) {
alert('您猜的数太小了');
} else {
alert('您猜对了');
break;//跳出死循环
}
}
2.11.2 Date()日期对象
-
Date 对象和 Math 对象不一样,他是一个构造函数,所以我们需要实例化后才能使用
-
Date 实例用来处理日期和时间
获取当前时间必须实例化:
var now = new Date();
console.log(now);
-
如果Date()不写参数,就返回当前时间
-
如果Date()里面写参数,就返回括号里面输入的时间
// 1.如果没有参数,返回当前系统的当前时间
var now = new Date();
console.log(now);
// 2.参数常用的写法 数字型 2019,10,1 字符串型 '2019-10-1 8:8:8' 时分秒
// 如果Date()里面写参数,就返回括号里面输入的时间
var data = new Date(2019,10,1);
console.log(data); //Date Fri Nov 01 2019 00:00:00 GMT+0800 (中国标准时间)
// 返回的是11月不是10月
var data2 = new Date('2019-10-1 8:8:8');
console.log(data2);//Date Tue Oct 01 2019 08:08:08 GMT+0800 (中国标准时间)
日期格式化
想要 2019-8-8 8:8:8 格式的日期
需要获取日期指定的部分,所以我们要手动的得到这种格式
方法名 | 说明 | 代码 |
---|---|---|
getFullYear() | 获取当年 | dObj.getFullYear() |
getMonth() | 获取当月(0-11) | dObj.getMonth() |
getDate | 获取当天日期 | dObj.getDate() |
getDay() | 获取星期几(周日0到周六6) | dObj.getDay() |
getHours() | 获取当前小时 | dObj.getHours() |
getMinutes() | 获取当前小时 | dObj.getMinutes() |
getSeconds() | 获取当前秒钟 | dObj.gerSeconds() |
var date = new Date();
console.log(date.getFullYear()); // 返回当前日期的年 2019
console.log(date.getMonth() + 1); //返回的月份小一个月 记得月份 +1
console.log(date.getDate); //返回的是几号
console.log(date.getDay()); //周一返回1 周6返回六 周日返回0
例:
// 写一个 2022年 7月 20日 星期三
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dates = date.getDate();
var arr = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
var day = date.getDay();
console.log('今天是' + year + '年' + month + '月' + dates + '日 ' + arr[day]);
获取日期的总的毫秒形式(时间戳)
-
date.valueOf() :得到现在时间距离1970.1.1总的毫秒数
-
date.getTime() :得到现在时间距离1970.1.1总的毫秒数
// 获取Date总的毫秒数 不是当前时间的毫秒数 而是距离1970年1月1号过了多少毫秒数
// 实例化Date对象
var date = new Date();
// 1 .通过 valueOf() getTime() 用于获取对象的原始值
console.log(date.valueOf()); //得到现在时间距离1970.1.1总的毫秒数
console.log(date.getTime());
// 2.简单的写法
var date1 = +new Date(); // +new Date()返回的就是总的毫秒数,
console.log(date1);
// 3. HTML5中提供的方法 获得总的毫秒数 有兼容性问题
console.log(Date.now());
用时间戳来实现倒计时:
function countDown(time) {
var nowTime = +new Date();//返回当前时间总的号秒数
var inputtime = +new Date(time);//返回用户输入时间总的毫秒数
var del = inputtime - nowTime;
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('2022-7-22 19:00:00'));
2.11.3 数组对象
1) 检测是否为数组
-
instanceof 运算符,可以判断一个对象是否属于某种类型,后面跟array,即判断对象是否属于数组
-
Array.isArray() 用于判断一个对象是否为数组,isArray() 是 HTML5 中提供的方法
var arr = [1, 23];
var obj = {};
console.log(arr instanceof Array); // true
console.log(obj instanceof Array); // false
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false
注: 当检测 Array 实例时,Array.isArray 优于 instanceof,因为 Array.isArray 能检测 iframes。
2)添加删除数组元素
方法名 | 说明 | 返回值 |
---|---|---|
push(参数) | 末尾添加一个或多个元素,注意修改原数组 | 返回新的数组长度 |
unshift(参数) | 向数组的开头添加一个或更多元素,注意修改原数组 | 返回新的数组长度 |
pop() | 删除数组最后一个元素 | 返回它删除的元素的值 |
shift() | 删除数组的第一个元素,数组长度减1,无参数,修改原数组 | 返回删除元素 |
- push方法
var arr = [1, 2, 3];
arr.push('mtdj');
console.log(arr);//[ 1, 2, 3, "mtdj" ]
例:
var arr = [1000, 2100, 3800, 1600, 2000, 1611, 1590]
var newarr = [];
for (var i = 0;i<arr.length;i++){
if(arr[i]<2000){
// newarr[newarr.length]=arr[i];
newarr.push(arr[i]);//用push方法将所要的值追加到新数组中
}
}
- unshift方法
var arr = [1, 2, 3];
console.log(arr.unshift('mtdj'));//返回数组长度:5
console.log(arr);//[ "mtdj" ,1, 2, 3]
- pop方法
var arr = [1, 2, 3, 'mtdj', 4, 5, 6, 7, '王路飞'];
console.log(arr.pop('mtdj'));//返回结果是 王路飞
console.log(arr);//[ 1, 2, 3, "mtdj", 4, 5, 6, 7 ]
- shift方法
var arr = [1, 2, 3, 'mtdj', 4, 5, 6, 7, '王路飞'];
console.log(arr.shift('mtdj'));//返回结果是 1
console.log(arr);//[ 2, 3, "mtdj", 4, 5, 6, 7, "王路飞" ]
3)数组排序
- 翻转数组
var arr = ['pink','red','blue'];
arr.reverse();
console.log(arr);
- 数组排序
var arr1 = [3,4,7,1];
arr1.sort();
console.log(arr1);//仅对位数相同的情况可行
// 对于双位数
var arr = [1,64,9,61];
arr.sort(function(a,b) {
return b - a; //降序的排列
return a - b; //升序
}
)
4)数组索引
- 根据字符返回索引数
方法名 | 说明 | 返回值 |
---|---|---|
indexOf() | 数组中查找给定元素的第一个索引 | 如果存在返回索引号,如果不存在,则返回-1 |
lastIndexOf() | 在数组的最后一个索引,从后向前索引 | 如果存在返回索引号,如果不存在,则返回-1 |
//返回数组元素索引号方法 indexOf(数组元素) 作用就是返回该数组元素的索引号
//它只发返回 第一个 满足条件的索引号
//如果找不到元素,则返回-1
var arr = ['red','green','blue'.'pink','blue'];
console.log(arr.indexOf('blue')); // 2
console.log(arr.indexOf('blue',3));//从索引号为3的位置往后开始寻找
//结果为: 4
console.log(arr.lastIndexOf('blue')); // 4
console.log(arr.lastIndexOf('blue',3));//从索引号为3的位置向前开始寻找
//结果为: 2
- 根据索引数返回字符
方法名 | 说明 | 使用 |
---|---|---|
charAt(index) | 返回指定位置的字符(index字符串的索引号) | str.charAt(0) |
charCodeAt(index) | 获取指定位置处字符的ASCII码(index索引号) | str.charCodeAt(0) |
str[index] | 获取指定位置处字符 | HTML,IE8+支持,和charAt()等效 |
数组去重案例:
-
分析:把旧数组里面不重复的元素选取出来放到新数组中,重复的元素只保留一个,放到新数组中去重。
-
核心算法:我们遍历旧数组,然后拿着旧数组元素去查询新数组,如果该元素在新数组里面没有出现过,我们就添加,否则不添加。
-
利用 新数组.indexOf(数组元素) 如果返回是 -1 就说明 新数组里面没有改元素
var arr = ['m', 'u', 't', 'o', 'u', 'd', 'a', 'n', 'j', 'u', 'a', 'n']
var newarr = [];
for (var i = 0; i < arr.length; i++) {
while (newarr.indexOf(arr[i]) === -1) { //注意比较运算符
newarr.push(arr[i]);
}
}
console.log(newarr);//[ "m", "u", "t", "o", "d", "a", "n", "j" ]
5)数组转化为字符串
方法名 | 说明 | 返回值 |
---|---|---|
toString() | 把数组转换成字符串,逗号分隔每一项 | 返回一个字符串 |
join(‘分隔符’) | 方法用于把数组中的所有元素转换为一个字符串,中间用分隔符分隔 | 返回一个字符串 |
// 1.toString() 将我们的数组转换为字符串
var arr = [1, 2, 3];
console.log(arr.toString()); // 1,2,3
// 2.join('分隔符')
var arr1 = ['green', 'blue', 'red'];
console.log(arr1.join()); // 不写默认用逗号分割
console.log(arr1.join('-')); // green-blue-red
console.log(arr1.join('&')); // green&blue&red
2.11.4 字符串对象
基本包装类型就是把简单数据类型包装成为复杂数据类型,这样基本数据类型就有了属性和方法。
JavaScript 提供了三个基本包装类型:String、Number和 Boolean。
var str = 'andy';
console.log(str.length);
1) 例:找出字符串里的u,并输出其出现的次数
var str = 'mutoudanjuan';
var num = str.indexOf('u');//第一个u
var i = 0;
while (num !== -1) {
i++;
console.log(num);
num = str.indexOf('u', num + 1);//num+1是指上一个u的索引号+1
}
console.log(i);
2) 例:统计出现次数最多的字符和其次数
- 核心算法:利用 charAt() 遍历这个字符串
- 把每个字符都存储给对象, 如果对象没有该属性,就为1,如果存在了就 +1
- 遍历对象,得到最大值和该字符
var str = 'mutoudanjuan';
var max = {};
for (var i = 0; i < str.length; i++) {
var chars = str.charAt(i);//遍历字符串,chars表示遍历出的字符
if (max[chars]) {//max[chars]得到的是属性值,没有时,值为undefined
max[chars]++;//如果有,就+1
} else {
max[chars] = 1;//如果没有,就赋值为1,例如i=0时max['m']=1
}
}
console.log(max);//输出的是所有的字符,和其出现的次数
//找到出现次数最多的字符和其次数次数
var a = 0//最大值
var ch = ''
for (var k in max) {//k得到的是属性名,max[k]得到的是属性值
if (max[k] > a) {
a = max[k];
ch = k;//出现次数最多的字符
}
}
console.log('出现次数最多的字符为:' + ch + ' 出现的次数为:' + a);
3) 字符串操作方法
方法名 | 说明 |
---|---|
concat(str1,str2,str3…) | concat() 方法用于连接两个或对各字符串。拼接字符串 |
substr(start,length) | 从 start 位置开始(索引号), length 取的个数。 |
slice(start,end) | 从 start 位置开始,截取到 end 位置 ,end 取不到 (两个都是索引号) |
substring(start,end) | 从 start 位置开始,截取到 end 位置 ,end 取不到 (基本和 slice 相同,但是不接受负) |
var str = '关于海贼王要出新电影,但我不知道什么时候能看到这件事'
console.log(str.substr(2, 3));//海贼王
4) replace()方法
-
replace() 方法用于在字符串中用一些字符替换另一些字符
-
其使用格式:replace(被替换的字符,要替换为的字符串)
var str = '今天周五,明天周六'
console.log(str.replace('周', '星期'));//今天星期五,明天周六
//如果有重复的字符,只会替换第一个
//如果有重复的字符,只会替换所有
var str = '今天周五,明天周六'
while (str.indexOf('周') !== -1) {
str = str.replace('周', '星期');
}
console.log(str);
5) split()方法
split() 方法用于切分字符串,将字符串依照分隔符切分为数组。在切分完毕之后,返回的是一个新数组。
//将字符串按照‘,’切分,再存放到一个数组中
var str='pink,blue,red,yellow'
console.log(str.split(','));//[ "pink", "blue", "red", "yellow" ]
2.12 简单类型与复杂类型
简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。
- 值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型:string ,number,boolean,undefined,null(null的返回值为object)
- 引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型:通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
2.12.1 堆和栈
-
栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;简单数据类型存放到栈里面
-
堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型存放到堆里面
注意:JavaScript中没有堆栈的概念,通过堆栈的方式,可以让大家更容易理解代码的一些执行方式,便于将来学习其他语言。
复杂数据类型(栈空间)里存放的是地址,真正的对象实例存放在堆空间中
function Person(name) {
this.name = name;
}
function f1(x) { // x = p,将 p 的地址赋给 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. 这个输出什么 ? 张学友
//p 和 x 的地址相同,因此输出相同