目录
一.计算机编程基础
1.计算机语言分类
- 机器语言,汇编语言,高级语言。
- ①机器语言:计算机最终所执行的都是 01机器语言。
- ②汇编语言:和机器语言实质相同,直接对硬件操作,但更好记。
2.翻译器
- 高级语言程序不能直接被计算机识别,必须经过转换,需要翻译器:将源代码转换为机器语言,也称二进制化。
3.编程语言和标记语言的区别
- 编程语言是主动的,有很强的逻辑性。
- 标记语言不向计算机发出指令,是被动的,用来被读取的。
4.数据存储
- 硬盘、内存保存的是 二进制数据;安装软件本质:把程序文件复制到硬盘中。
- 数据存储单位:
- 位(bit): 1bit 可以保存一个 0 或者 1 (最小的存储单位)
- 字节(Byte):1B = 8b
- 千字节(KB):1KB = 1024B
- 兆字节(MB):1MB = 1024KB
- 吉字节(GB): 1GB = 1024MB
- 太字节(TB): 1TB = 1024GB
- 计算机运行软件的过程:
- 打开某个程序时,先从 硬盘 中把程序的代码加载到 内存 中。
- CPU执行 内存 中的代码(cpu运行快,只从硬盘读数据浪费cpu性能,用内存过渡(内存是电,硬盘是机械)
二.初识 JavaScript
1.JavaScript 定义
- 运行在客户端的脚本语言 (Script 是脚本的意思)。
- 不需要编译,运行过程中由 JS 解释器(JS引擎)【逐行】解释并执行,浏览器本身不执行 JS 代码。
- 现在也可以基于 Node.js 技术进行服务器端编程。
- 使用方式:行内式、内嵌式、外部JS。
<head> <!-- 2.内嵌式的js --> <script> // alert('沙漠骆驼'); </script> <!-- 3. 外部js script 双标签 --> <script src="my.js"></script> </head> <body> <!-- 1. 行内式的js 直接写到元素的内部 --> <!-- <input type="button" value="唐伯虎" onclick="alert('秋香姐')"> --> </body>
- 浏览器分成两部分:渲染引擎 和 JS 引擎
- 渲染引擎:用来解析HTML与CSS,俗称内核,比如 chrome 浏览器的 blink ,老版本的 webkit
- JS 引擎:也称为 JS 解释器。 用来读取网页中的JavaScript代码,对其处理后运行,比如 chrome 浏览器的 V8
2.JavaScript 作用
- 表单动态校验(密码强度检测) ( JS 产生最初的目的 )
- 网页特效
- 服务端开发(Node.js)
- 桌面程序(Electron)
- App(Cordova)
- 控制硬件-物联网(Ruff)
- 游戏开发(cocos2d-js)
3.JavaScript 组成
- ECMAScript:规定 JS 的基础语法。
- DOM(文档对象模型):提供接口,对页面上的各种元素进行操作(大小、位置等)。
- BOM(浏览器对象模型):提供与浏览器窗口进行互动的对象结构,如弹出框、控制浏览器跳转、获取分辨率等。
4.JavaScript 输入输出语句
方法 说明 归属 alert(msg) 浏览器弹出警示框(显示消息给用户看) 浏览器 console.log(msg) 浏览器控制台打印输出信息(显示消息给程序员看) 浏览器 prompt(info) 浏览器弹出输入框(用户可以输入) 浏览器 // 弹出一个输入框(prompt),让用户输入年龄(用户输入) 并用一个变量保存输入值 // 把用户输入的值用变量保存起来,把刚才输入的年龄与所要输出的字符串拼接 // 使用alert语句弹出警示框 输出拼接结果 var age = prompt('请输入您的年龄'); var str = '您今年已经' + age + '岁了'; alert(str);
三.JavaScript 变量
1.定义变量
- 变量:用于存放数据的容器,通过 变量名 获取 / 修改数据。
- 变量本质:是内存里的一块空间,用来存储数据。
2.使用变量
- 声明变量 var:计算机会自动为变量分配内存空间。
- 变量名 xx:通过变量名访问内存中分配的空间。
- 变量初始化:声明一个变量并赋值(如 var age = 18;)。
- 声明多个变量:写一个 var, 多个变量名间用 英文逗号 隔开 并 换行(如var age = 10, name = 'xyc', sex = 2; )。
var age = 10, name = 'xyc', sex = 2;
- 特殊情况:
情况 说明 结果 var age ; console.log (age);
只声明 不赋值 undefined console.log(age) 不声明 不赋值 直接使用 报错 age = 10; console.log (age); 不声明 只赋值 10 - 交换两个变量的值:
// 1. 把apple1 的值给临时变量 temp // 2. 把apple2 的值给 apple1 // 4. 把temp 的值给 apple2 var temp; // 声明了一个临时变量 为空 var apple1 = '青苹果'; var apple2 = '红苹果'; temp = apple1; // 把右边给左边 apple1 = apple2; apple2 = temp;
四.JavaScript 数据类型
1.数据类型定义
- 数据类型决定了如何将代表这些值的位存储到计算机的内存中。
- JavaScript 是一种弱类型 / 动态语言。即不用提前声明变量类型,程序运行过程中,类型会被自动确定。
- JS 是动态语言,变量的数据类型是 可以变化 的。
// js是动态语言 变量的数据类型是可以变化的 var x = 10; // x 是数字型 x = 'pink'; // x 字符串型
2.数据类型分类
- JS 数据类型分为两类:
- 简单数据类型 (Number,String,Boolean,Undefined,Null)
- 复杂数据类型 (object)
3.数字型 Number
3.1 JavaScript 中数值的最大和最小值
- 最大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308
- 最小值:Number.MIN_VALUE,这个值为:5e-32
3.2 数字型三个特殊值
- Infinity :代表无穷大,大于任何数值。
- -Infinity :代表无穷小,小于任何数值。
- NaN :Not a number,代表一个非数值。
- isNaN():判断变量是否为 非数值,返回 true 或 false。
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 非数值 console.log(isNaN(12)); // false 不是非数值 console.log(isNaN('黄焖鸡米饭')); // true 是非数值
4.字符串型 String
- JS 可以用单引号嵌套双引号 ,或者用双引号嵌套单引号 (外双内单,外单内双)。
- 不加引号会报错,HTML 使用 双引号,所以 JS 推荐 单引号。
var strMsg = '我是"高帅富"程序猿'; // 可以用''包含"" var strMsg2 = "我是'高帅富'程序猿"; // 也可以用"" 包含''
- 字符串转义字符:
转义符 解释说明 \n 换行符,n 是 newline 的意思 \ \ 斜杠 \ \t tab 缩进 \b 空格 ,b 是 blank 的意思 - 字符串长度:string.length
- 字符串相连:字符串 + 任何类型 = 拼接之后的新字符串,看下面1.3
//1.1 字符串 "相加" alert('hello' + ' ' + 'world'); // hello world //1.2 数值字符串 "相加" alert('100' + '100'); // 100100 //1.3 数值字符串 + 数值 alert('11' + 12); // 1112 //1.4 数值 + 数值 alert(11 + 12); // 23
5.布尔型 Boolean
console.log(true + 1); // 2 true相当于1 console.log(false + 1); // 1 false相当于0
6.Undefined 和 Null
- 一个变量 声明后没有被赋值:会有默认值 undefined ( 相连【字符串+undefined】、相加【NaN】)。
var variable; console.log(variable); // undefined console.log('你好' + variable); // 你好undefined console.log(11 + variable); // NaN console.log(true + variable); // NaN
- 一个变量 声明后给 null 值:里面存的值为空(相连【字符串+null】、相加【其他变量不变】 区分对象部分 null)。
var vari = null; console.log('你好' + vari); // 你好null console.log(11 + vari); // 11 console.log(true + vari); // 1
7.获取变量数据类型 (typeof 变量名)
- prompt 取过来的值是 字符型的。
// prompt 取过来的值是 字符型的 var age = prompt('请输入您的年龄'); console.log(typeof age); //结果为 String
- typeof null 是非常特殊的,他返回的是"object"
8.数据类型转换
8.1 转换为字符串
- 三种转换方式:变量.toString()、String(变量) 、利用 + 拼接字符串 实现转换(隐式转换)。
- 更多用第三种 加号拼接字符串 转换方式, 这一种方式也称为隐式转换。
<script> // 1. 变量.toString() var num = 10; var str = num.toString(); console.log(str); // 2. String(变量) console.log(String(num)); // 3. 利用 + 拼接字符串 实现转换效果 隐式转换 console.log(num + ''); </script>
8.2 转换为数字型(重点)
- parseInt(变量) 可以把 字符型的转换为数字型 得到是 整数,注意 parseInt 和 parseFloat 大小写。
- parseFloat(变量) 可以把 字符型的转换为数字型 得到是 浮点数,注意 parseInt 和 parseFloat 大小写。
- 上面两种方式不会四舍五入 可以去除数字开头的单位。
- Number(变量)
- 利用算数运算 - * / 隐式转换
<script> var age = prompt('请输入您的年龄'); 前面说了prompt 获取的用户输入数据是 String 类型 // 1. parseInt(变量) 可以把 字符型的转换为数字型 得到是 整数 console.log(parseInt(age)); console.log(parseInt('3.14')); // 3 取整 console.log(parseInt('3.94')); // 3 取整 不会四舍五入 console.log(parseInt('120px')); // 120 会去到这个px单位 console.log(parseInt('rem120px')); // NaN 数字在最前面 否则不能去除单位 // 2. parseFloat(变量) 可以把 字符型的转换为数字型 得到是 浮点数 console.log(parseFloat('3.14')); // 3.14 console.log(parseFloat('120px')); // 120 会去掉这个px单位 console.log(parseFloat('rem120px')); // NaN // 3. Number(变量) var str = '123'; console.log(Number(str)); console.log(Number('12')); // 4. 利用算数运算 - * / 隐式转换 console.log('12' - 0); // 12 console.log('123' - '120'); console.log('123' * 1); </script>
- 计算年龄实例:
var year = prompt('请您输入您的出生年份'); //(用户输入) var age = 2020 - year; // year 取过来的是字符串型 这里用减法 有隐式转换(程序内部处理) alert('您今年已经' + age + '岁了'); //(输出结果)
- 加减计算实例:
var num1 = prompt('请您输入第一个值:'); var num2 = prompt('请您输入第二个值:'); var result = parseFloat(num1) + parseFloat(num2); //此处转换为数字类型 alert('您的结果是:' + result);
8.3 转换为布尔型
- 代表空、否定的值会被转换为 false ,如 ''、0、NaN、null、undefined
- 其余值都会被转换为 true
console.log(Boolean('')); // false console.log(Boolean(0)); // false console.log(Boolean(NaN)); // false console.log(Boolean(null)); // false console.log(Boolean(undefined)); // false console.log(Boolean('比特是狗')); // true console.log(Boolean(12)); // true
五.标识符、关键字、保留字
1.解释型语言和编译型语言
- 翻译器翻译的方式有两种:一个是编译,一个是解释。两种方式区别在于翻译的时间点不同。
- 编译器:在 代码执行之前 进行编译,生成中间代码文件(如 Java 中的 .class 文件)。
- 解释器:在 运行时 进行解释,并立即执行(当编译器以解释方式运行的时候,也称之为解释器)。
2.标识符
- 指开发人员为变量、属性、函数、参数取的名字,不能是关键字或保留字。
3.关键字
- 指 JS 本身已经使用了的字,不能再用它们充当变量名、方法名。
- 包括:break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with 等。
4.保留字
- 指预留的“关键字”,现在虽然还不是关键字,但是未来可能会成为关键字,同样不能使用它们当变量名或方法名。
- 包括:boolean、byte、char、class、const、debugger、double、enum、export、extends、fimal、float、goto、implements、import、int、interface、long、mative、package、private、protected、public、short、static、super、synchronized、throws、transient、volatile 等。
- 注意:如果将保留字用作变量名或函数名,那么除非将来的浏览器实现了该保留字,否则可能收不到任何错误消息。
六.JavaScript 运算符(操作符)
1.运算符(操作符)分类
- 算数运算符
- 递增和递减运算符
- 比较运算符
- 逻辑运算符
- 赋值运算符
2.算数运算符
浮点数的精度问题
浮点数值的最高精度是 17 位小数,但进行算术计算时 精确度 远不如整数。
所以:不要直接判断两个浮点数是否相等 !
var result = 0.1 + 0.2; // 结果不是 0.3,而是:0.30000000000000004 console.log(0.07 * 100); // 结果不是 7,而是:7.000000000000001 // 不能直接拿着浮点数进行比较 var num = 0.1 + 0.2; console.log(num == 0.3); // false
3.递增和递减运算符
3.1 前置递增运算符(先自加,后返回值)
var num = 10; alert(++num + 10); //21 //先执行 ++num 这个表达式,使之结果为11 //再执行 ++num + 10 这个表达式,使之结果为21
3.2 后置递增运算符(先返回原值,后自加)
var num = 10; alert(10 + num++); // 20 //先执行 10 + num++ 这个表达式,使之结果为20,此时是 num++ = 10 参与计算 //再执行 num++ 这个表达式,使之结果为11
3.3 练习
var e = 10; var f = e++ + ++e; // 1. e++ = 10 e = 11 2. e = 12 ++e = 12 console.log(f); // 22 // e++:e 本身先不变化,e++ 运算得到10,e 在 e++ 算完后自加得到 11,e=11参与下面的运算 // ++e:e 本身先变化 得到 12,++e 运算得到 12
4.比较运算符
- 程序里的等于符号 是 == 默认转换数据类型 会把字符串型的数据转换为数字型 只要求值相等就可以。
- 程序里面有全等 要求 两侧的值 还有 数据类型完全一致。
//1. 程序里的等于符号 是 == 默认转换数据类型 会把字符串型的数据转换为数字型 只要求值相等就可以 console.log(18 == '18'); // true console.log('茶茶子' == '不喜欢特特'); // flase // 2. 程序里面有全等 要求 两侧的值 还有 数据类型完全一致 console.log(18 === 18); // true console.log(18 === '18'); // false
5.逻辑运算符
- 分类:逻辑与&&、逻辑或||、逻辑非!
- 短路运算(逻辑中断):当有多个表达式时,假设左边表达式可以确定结果,就不再继续运算右边的表达式。
- 逻辑与:表达式1 && 表达式2,左真返右,左假返左。(简单理解:一个为假就是假)
//如果 表达式1 的值为真,则返回 表达式2 //如果 表达式1 的值为假,则返回 表达式1 // 如果有空的或者否定的为假 其余是真的 0 '' null undefined NaN console.log( 123 && 456 ); // 456 console.log( 0 && 456 ); // 0 console.log('' && 1 + 2 && 456 * 56789); // ''
- 逻辑或:表达式1 || 表达式2,左真返左,左假返右。(简单理解:一个为真就是真)
//如果 表达式1 的值为真,则返回 表达式1 //如果 表达式1 的值为假,则返回 表达式2 console.log( 0 || 456 ); // 456 console.log( 123 || 456 || 789 ); // 123
6.赋值运算符
var age = 10; age += 5; // 相当于 age = age + 5; age *= 10; // 相当于 age = age * 10;
7.运算符优先级
七.JavaScript 流程控制
1.流程控制三种结构
- 顺序结构、分支结构、循环结构。
2.顺序流程控制
- 程序会按照代码的 先后顺序,依次执行。
3.分支流程控制
3.1 分支结构定义
- 根据不同条件,执行不同路径代码(执行代码多选一的过程),得到不同结果。
- JS 提供两种分支结构语句:if 语句、switch 语句。
3.2 if 语句
3.2.1 if
if (条件表达式) { // 条件成立执行的代码语句 否则什么也不做 }
3.2.2 if else(双分支) 判断闰年案例
var year = prompt('请您输入年份:'); if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { alert('您输入的年份是闰年'); } else { alert('您输入的年份是平年'); }
3.2.3 if else if(多分支) 判断成绩案例
// 按照从大到小的思路来写 var score = prompt('请您输入分数:'); if (score >= 90) { alert('宝贝,你是我的骄傲'); } else if (score >= 80) { alert('宝贝,你已经很出色了'); } else if (score >= 70) { alert('你要继续加油喽'); } else { alert('等着挨打吧'); }
3.3 三元表达式
- 表达式1 ? 表达式2 : 表达式3
- 1真执行2,1假执行3,类似于if else (双分支) 的简写。
- 时间数字补 0 案例
var time = prompt('请您输入一个 0 ~ 59 之间的一个数字'); var result = time < 10 ? '0' + time : time; // 把返回值赋值给一个变量 alert(result);
3.4 switch 语句
- 当要针对变量设置一系列的 固定值 的选项时,使用 switch。
switch :开关 转换 , case :小例子 选项- 执行 case 里面的语句时,如果没有break,则继续执行下个 case 里面的语句。
- switch 中的值 必须和 case 中的值 全等=== 即 数值+类型 完全相同。
- 查询水果案例
// case 后面的值写水果名称,一定要加引号 ,因为必须是全等匹配。 var fruit = prompt('请您输入查询的水果:'); switch (fruit) { case '苹果': alert('苹果的价格是 3.5/斤'); break; case '榴莲': alert('榴莲的价格是 35/斤'); break; default: alert('没有此水果'); }
3.5 switch 语句和 if else if 语句的区别
- switch 语句通常处理 case 为 确定值 的情况, 而 if…else…语句更加灵活,常用于 范围判断。
- switch 语句仅执行符合条件的代码,效率更高。而if…else 语句所有条件代码都得执行,效率不如前者。
- 当分支比较少时,if… else 语句的执行效率高。
- 当分支比较多时,switch 语句的执行效率高,而且结构更清晰。
4.循环流程控制
4.1 for 循环(与计数有关)
4.1.1 for 循环重复 相同 的代码
var num = prompt('请输入次数:'); for ( var i = 1 ; i <= num; i++) { console.log('特特喜欢茶茶'); }
4.1.2 for 循环重复 不相同 的代码
for (var i = 1; i <= 100; i++) { if (i == 1) { console.log('特特今年1岁了, 他出生了'); } else if (i == 100) { console.log('茶茶今年100岁了,她死了'); } else { console.log('他们今年' + i + '岁了'); }}
4.1.3 断点调试过程
- 浏览器中按 F12 --> sources --> 找到需要调试的文件 --> 在程序的某一行设置断点。
- Watch:监视,通过 watch 可以监视变量的值的变化,非常常用。
- 浏览器中按 F11,让程序一行一行的执行,观察 watch 中变量的值的变化。
- 班级平均成绩案例
var num = prompt('请输入班级的总人数:'); // num 总的班级人数 var sum = 0; // 求和的变量 var average = 0; // 求平均值的变量 for (var i = 1; i <= num; i++) { var score = prompt('请您输入第' + i + '个学生成绩'); // 因为从prompt取过来的数据是 字符串型的需要转换为数字型 sum = sum + parseFloat(score); } average = sum / num; alert('班级总的成绩是' + sum); alert('班级平均分是:' + average);
4.2 双重 for 循环
- 外层循环执行一次,内层循环要执行全部次数。
- 打印 n行n列 星星案例(逻辑:内层循环负责打印一行 n个 星星,外层循环负责打印 n行)
var rows = prompt('请您输入行数:'); // 行 var cols = prompt('请您输入列数:'); // 列 var str = ''; // 原来的星星是 一个空的字符串 for (var i = 1; i <= rows; i++) { // 外层循环 负责打印总行数 for (var j = 1; j <= cols; j++) { // 内层循环 负责打印每行个数 str = str + '★'; // 在空字符串基础上不断链接星星字符串 } str += '\n'; // 打印了一行星星之后 记得给这行追加换行符号 } console.log(str);
- 打印乘法表案例(逻辑:外层循环负责行数,内层循环负责每行公式,每行公式的个数 = 行数, j <= i;)
// 外层的 for 循环控制行数 i ,循环9次 ,可以打印 9 行 // 内层的 for 循环控制每行公式 j // 核心算法:每一行 公式的个数正好和行数一致, j <= i; // 每行打印完毕,都需要重新换一行 var str = ''; // 最初的乘法表是空的 for (var i = 1; i <= 9; i++) { // 外层循环 控制行数 i,打印9行 for (var j = 1; j <= i; j++) { // 内层循环 控制每行公式个数 j j = i str += j + '×' + i + '=' + i * j + '\t'; // 空字符串追加乘法公式 } str += '\n'; // 打印完一行乘法公示后记得换行 } console.log(str);
输出结果:
4.3 while 循环
- 使用 while 循环时一定要有 退出条件(完成计数器更新),否则会成为死循环。
var num = 1; // 计数器 初始化变量 while (num <= 100) { console.log('特特喜欢茶茶'); num++; // 操作表达式 完成计数器的更新 防止死循环 }
4.4 do-while 循环
// 至少执行一次 do { var message = prompt('特特你喜欢我吗?'); } while (message !== '我喜欢你') alert('我也喜欢你ww');
4.5 区分 continue、break
- continue 关键字 退出本次(当前次的循环) 继续执行剩余次数循环
- break 关键字 退出整个循环
- 求除了能被7整除之外的整数的和案例(continue应用)
var sum = 0; for (var i = 1; i <= 100; i++) { if (i % 7 == 0) { continue; // 只要遇见 continue就退出本次循环 直接跳到 i++ } sum += i; } console.log(sum);
八.JavaScript 数组
1.数组定义
- 数组是指 一组数据的集合,其中的每个数据被称作 元素,在数组中可以 存放任意类型的元素。
- 数组是一种将一组数据存储在单个变量名下的 优雅方式。
2.创建数组
- 利用 new 创建数组
// 创建一个新的空数组,注意 Array(),A 要大写 var arr = new Array();
- 利用 数组字面量 创建数组(使用最多)
// 使用 数组字面量方式 创建数组 var 数组名 = []; // 创建了一个空的数组 var cute = ['一只特特','一只茶茶','一只桃西西']; // 数组元素用逗号间隔
- 数组元素的类型:数组中可以存放任意类型的数据,例如字符串,数字,布尔值等。
var arrStus = ['茶茶',20,true];
3.获取数组中的元素
- 数组通过索引操作对应的数组元素:数组名[索引号],索引号从 0 开始。
- 如果访问时数组没有和索引号对应的元素,则输出值是 undefined。
var arrStus = [1,2,3]; // 定义数组 alert(arrStus[1]); // 获取数组中的第2个元素 alert(arrStus[3]); // 没有这个数组元素 输出的结果是 undefined
4.遍历数组
4.1 数组遍历(for 循环)
var arr = ['red','green', 'blue']; for(var i = 0; i < arr.length; i++){ // 数组索引号从0开始 ,所以 i 必须从 0 开始 console.log(arrStus[i]); // arr.length 动态监测数组元素的个数 方便随时追加并遍历 }
4.2 数组的长度(指数组元素的个数)
- 数组的 length 属性可以被修改。
- 如果 length 大于数组元素个数,则会在数组末尾追加空白元素。
- 如果 length 小于数组元素个数,则会把超过的数组元素删除。
数组索引号和数组长度: 索引号从 0 开始是 下标, 数组长度是 元素个数。// 将数组 ['red', 'green', 'blue', 'pink'] 转换为字符串,并且用 | 或其他符号分割 var arr = ['red', 'green', 'blue', 'pink']; var str = ''; // 采用字符串追加的方式 实现数组到字符串的转换 var sep = '|'; // 分割符号变量 for (var i = 0; i < arr.length; i++) { // 遍历数组 str += arr[i] + sep; // 给空字符串追加 数组元素 以及 分割符号 } console.log(str);
5.数组中新增元素
- ① 修改 length 长度
// 1. 新增数组元素 修改length长度 var arr = ['red', 'green', 'blue']; // 此时数组长度是3 arr.length = 5; // 数组的长度修改为了 5 里面应该有5个元素 console.log(arr); //会有五个元素 但其中两个因为是空的不显示 console.log(arr[3]); // undefined console.log(arr[4]); // undefined
- ② 修改索引号,追加数组元素
// 2. 新增数组元素 修改索引号 追加数组元素 var arr1 = ['red', 'green', 'blue']; arr1[3] = 'pink'; arr1[4] = 'hotpink'; arr1[0] = 'yellow'; // 这里是替换原来的数组元素 console.log(arr1); arr1 = '就这?'; console.log(arr1); // 不要直接给 数组名赋值 否则里面的数组元素都没有了
6.筛选数组元素
- 将数组 [2, 0, 6, 1, 77, 0, 52, 0, 25, 7] 中大于等于 10 的元素选出来,放入新数组。
- 思路:声明新数组,遍历旧数组,用 新数组[新数组长度] 来给新数组追加符合要求的数组元素。
var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7]; var newArr = []; // 1、声明一个新的数组用于存放新数据newArr。 for (var i = 0; i < arr.length; i++) { // 2、遍历原来的旧数组, 找出大于等于 10 的元素。 if (arr[i] >= 10) { newArr[newArr.length] = arr[i]; // 3、刚开始 newArr.length 就是 0依次追加给新数组 newArr 追加之后 newArr.length 会自动改变 } } console.log(newArr);
7.数组元素去重
- 将数组[2, 0, 6, 1, 77, 0, 52, 0, 25, 7]中的 0 去掉后,形成一个不包含 0 的新数组。
- 思路:声明新数组,遍历旧数组,用 新数组[新数组长度] 来给新数组追加符合要求的数组元素。
// 3、新数组里面的个数, 用 length 不断累加。 var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7]; var newArr = []; // 1、新建一个数组用于存放筛选之后的数据 for (var i = 0; i < arr.length; i++) { // 2、遍历原来的数组 if (arr[i] != 0) { newArr[newArr.length] = arr[i]; // 3、把不是 0 的数据添加到新数组里 } } console.log(newArr);
8.数组翻转
- 将数组 ['red', 'green', 'blue', 'pink', 'purple'] 的内容反过来存放
- 思路:反过来遍历原数组
var arr = ['red', 'green', 'blue', 'pink', 'purple', 'hotpink']; var newArr = []; // 1、声明一个新数组 newArr for (var i = arr.length - 1; i >= 0; i--) { //2、反过来遍历原来的数组 newArr[newArr.length] = arr[i] } console.log(newArr);
9.冒泡排序
var arr = [4, 1, 2, 3, 5]; for (var i = 0; i <= arr.length - 1; i++) { // 外层循环趟数 for (var j = 0; j <= arr.length - i - 1; j++) { // 里面的循环 每一趟的交换次数 // 内部交换2个变量的值 前一个和后面一个数组元素相比较 if (arr[j] < arr[j + 1]) { var temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } console.log(arr);
九.JavaScript 函数
1.函数定义
- 函数:封装了一段 可被重复调用执行 的代码块。
2.函数的使用(声明+调用)
2.1 声明函数
// 声明函数 function 关键字,必须小写 function 函数名() { // 函数名命名一般是动词 // 函数体代码 }
2.2 调用函数
调用函数不要忘记添加小括号:函数名();
声明函数 本身并不会执行代码,只有 调用函数 时才会执行 函数体代码。
2.3 函数封装
- 函数的封装是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口。
// 声明函数 不执行代码 function getSum(){ var sumNum = 0;// 准备一个变量,保存数字和 for (var i = 1; i <= 100; i++) { sumNum += i;// 把每个数值 都累加 到变量中 } alert(sumNum); } // 调用函数 执行代码 getSum();
3.函数的参数
3.1 函数参数语法
- 调用的时候 实参 传递给 形参。
- 形参默认值 undefined。
// 带参数的函数声明 function 函数名(形参1, 形参2 , 形参3...) { // 可以定义任意多的参数,用逗号分隔 // 函数体 } // 带参数的函数调用 函数名(实参1, 实参2, 实参3...);
3.2 函数形参和实参数量不匹配时
- 函数可以带参数也可以不带参数。
- 声明函数的时候,函数名括号里面的是形参,形参相当于不用声明的变量。
- 调用函数的时候,函数名括号里面的是实参。
- 多个参数中间用逗号分隔。
- 形参的个数 可以 和实参个数不匹配,但是结果不可预计(undefined / null),尽量要匹配。
4.函数的返回值
- return 终止函数,并返回指定的值,return 后的代码不执行。
- 如果函数没有 return ,返回的值是 undefined。
- return 只能返回一个值,如:return num1, num2; // 返回结果是 最后一个 的值。
- return 如果想返回多个值,可以考虑数组,如: return [num1 + num2, num1 * num2, num1 / num2];。
- 实际开发里,经常用一个变量来接受 函数的返回结果 如:var re = getArrMax([5, 2, 99, 101, 67, 77]);。
function fun1() { return 666; } console.log(fun1()); // 返回 666 function fun2() {} console.log(fun2()); // 返回 undefined
- break ,continue ,return 的区别:
- break :结束当前的循环体(如 for、while)。
- continue :跳出本次循环,继续执行下次循环(如 for、while)。
- return :不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码。
5.arguments 的使用
- 只有函数才有 arguments 对象 而且是每个函数都内置好了 arguments。
- 当不确定有多少个参数传递的时候,可以用 arguments 来获取。
- arguments 对象中存储了传递的 所有实参,在函数内部使用。
- arguments 是一个伪数组,因此 可以遍历。
- 关于伪数组:
- 具有 length 属性
- 按索引方式储存数据
- 不具有数组的 push() , pop() 等方法
// 利用函数求任意个数的最大值(不确定输入数,考虑 arguments) function getMax() { //里面存储了所有实参 arguments = [1,2,3] + arguments = [1, 2, 3, 4, 5]... var max = arguments[0]; // 设第一个元素为最大值 for (var i = 1; i < arguments.length; i++) { // arguments.length if (arguments[i] > max) { // 可以按照数组的方式遍历 arguments max = arguments[i]; } } return max; } console.log(getMax(1, 2, 3)); console.log(getMax(1, 2, 3, 4, 5));
6.函数案例
6.1 判断二月天数
- 利用知识点:函数可以互相调用
// 用户输入年份,输出当前年份2月份的天数 function backDay() { var year = prompt('请您输入年份:'); if (isRunYear(year)) { // 只有是闰年时 才是true if分支才可以执行 alert('当前年份是闰年2月份有29天'); } else { alert('当前年份是平年2月份有28天'); } } backDay(); //先执行这个方法调用 再跳转到上面的函数 再通过上面的函数调用下面的函数 // 判断是否为闰年的函数 function isRunYear(year) { // 如果是闰年我们返回 true 否则 返回 false var flag = false; if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { flag = true; } return flag; }
6.2 利用函数书写冒泡排许
// 利用函数冒泡排序 sort 排序 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 arr1 = sort([1, 4, 2, 9]); console.log(arr1); var arr2 = sort([11, 7, 22, 999]); console.log(arr2);
7.函数的两种声明方式
7.1 自定义函数方式 ( 命名函数 )
// 声明定义方式 function fn() {} // 调用 fn();
- 函数调用的代码 既可以放到声明函数的前面,也可以放在声明函数的后面。
7.2 函数表达式方式 ( 匿名函数)
// 函数表达式写法,匿名函数后面跟分号结束,类似于变量声明 var fn = function(){}; // 调用的方式,函数调用 必须写到 函数体下面 fn(); //fn是变量名,不是函数名
- 类似于声明变量,存储值是函数,里面的函数是没有名字的,fn 指得是变量名字,记得分号。
- 函数调用的代码 必须 写到函数体后面。
十.JavaScript 作用域
1.全局作用域和局部作用域
- 全局作用域:作用于所有代码执行的环境。
- 局部作用域:作用于函数内的代码环境,也称为函数作用域。
- 目的:减少命名冲突。
- JS 没有块级作用域 {}(ES6之前)
if(true){ int num = 123; system.out.print(num); // java输出:123 js输出:123 } system.out.print(num); // java输出:报错 js输出:123 // java代码会报错,因为代码中 {} 即一块作用域,其中声明的变量 num,在 “{}” 之外不能使用 // js中没有块级作用域(在ES6之前)
2.全局变量和局部变量
- 在全局作用域下声明的变量 是全局变量 :任何位置都可以使用 浏览器关闭时才会被销毁 比较占内存。
- 如果在函数内部 没有声明(写 var),直接赋值 的变量也属于全局变量(不建议使用)。
- 在函数内部声明的变量 是局部变量 :只能在该函数内部使用 代码结束就销毁 节约内存。
- 函数的形参实际上就是局部变量。
var num = 10; // num 是全局变量 任何位置都能使用 function fun(aru) { var num1 = 10; // num1 是局部变量 只能在函数内部使用 num2 = 20; // 因为没使用函数声明var 就直接赋值 所以即使在函数内部 num2 依旧是全局变量 }
3.作用域链
- 采取 就近原则 方式来查找变量最终值。
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); //a的值 ? 4 就近 console.log(b); //b的值 ? 字符串22 就近 } } } fn1();
十一.JavaScript 预解析
1.预解析定义
- 把 变量和函数 的声明 在代码执行之前执行完成,也叫变量 / 函数提升。
2.变量预解析
- 变量提升(变量预解析): 变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升。
3.函数预解析
- 函数提升(函数预解析): 函数的声明会被提升到当前作用域的最上面,但是不会调用函数。
4.案例解析
var num = 10; fun(); function fun() { console.log(num); var num = 20; } // 相当于执行了以下操作 // var num; // 变量声明提升 // function fun() { // 函数声明提升 // var num; // 函数内部变量声明提升 // console.log(num); // 函数内部代码顺序执行 控制台输出 // num = 20; // 函数内部代码顺序执行 赋值 // } // num = 10; // 外部函数顺序执行 赋值 // fun(); // 外部函数顺序执行 调用内部函数
5.关于集体声明 和 预解析
f1(); console.log(c); console.log(b); console.log(a); function f1() { var a = b = c = 9; console.log(a); console.log(b); console.log(c); } // 相当于以下代码 // function f1() { // var a; // 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); // } // f1(); // console.log(c); // console.log(b); // console.log(a);
十二.JavaScript 对象
1.使用字面量创建对象(键值对)
var obj = {}; // 创建了一个空的对象 var MeowMeowTea = { name : 'MeowMeowTea', // 键:属性名 值:属性值 age : 20, // 多个属性 用逗号隔开 sex : '女', sayHi : function(){ // 这是匿名函数 alert('茶茶喜欢特特'); } }; // 不要忘记;
2.使用对象
- 对象包括 属性 和 方法
- 对象属性调用①:对象.属性名 ,这个小点 . 理解为“ 的 ”。
- 对象属性调用②:对象[‘属性名’],方括号里面的属性必须加引号。
- 对象方法调用:对象.方法名() ,方法名字后面一定加括号。
console.log(MeowMeowTea.name); // 调用名字属性 注意小点 console.log(MeowMeowTea['name']); // 调用名字属性 注意方括号单引号 MeowMeowTea.sayHi(); // 调用方法 记得别忘记()
- 区分 变量、属性、函数、方法:
- 变量 / 函数:单独声明赋值,单独存在,不是对象的一部分。
- 属性 / 方法:对象里面的变量称为属性,不需要声明,是对象的一部分。
3.使用 new Object 创建对象
var s = new Obect(); // Object() :第一个字母大写 此时创建了一个空对象 s.name = 'Tea'; // 利用 = 赋值的方法 添加对象的属性和方法 s.age = 20; // 每个属性和方法之间用 分号 结束 s.sex = '女'; s.sayHi = function(){ alert('特特喜欢茶茶'); }
4.使用构造函数创建对象(对象实例化)
- 使用构造函数的原因:把对象里 相同的属性和方法 抽象出来 封装到 函数 里,减少重复代码。
- 前面两种方法每次只能创建一个对象,构造函数每次可创建多个对象。
- 构造函数约定 首字母大写。
- 函数内的属性和方法前面需要添加 this ,表示当前对象的属性和方法。
- 构造函数中 不需要 return 返回结果。
- 创建对象的时候,必须用 new 来调用构造函数。
function Star(uname, age, sex) { // 1. 构造函数名字首字母要大写 this.name = uname; // 属性和方法前面必须添加 this this.age = age; this.sex = sex; this.sing = function(sang) { console.log(sang); } } var obj1 = new Star('茶茶子', 20, '女'); // 用 new 调用函数返回的是一个对象
- new关键字的作用:
- 在构造函数代码开始执行之前,创建一个空对象;
- 修改this的指向,把 this 指向创建出来的空对象;
- 执行构造函数里面的代码,给这个空对象添加属性和方法;
- 在函数完成之后,返回 this,即创建出来的对象。
5.遍历对象
for (var k in obj) { // key 是变量 可以自己改名 obj是对象名字 console.log(k); // 这里的 k 是属性名 console.log(obj[k]); // 这里的 obj[k] 是属性值 }
十三.JavaScript 内置对象
1.内置对象前言
- JavaScript 中的对象分为3种:自定义对象 、内置对象、 浏览器对象 (JS 独有)。
- JS 基础内容包括:自定义对象 + 内置对象,属于 ECMAScript。
- 内置对象最大的优点:帮助我们快速开发。
- JavaScript 提供了多个内置对象:Math、 Date 、Array、String 等。
- 查阅文档:开发者网络(MDN)、W3C。
- MDN:https://developer.mozilla.org/zh-CN/
2.Math对象(不是构造函数)
- 不需要实例化 Math (即使用 new 调用)就可以调用里面的属性方法。
获取指定范围内的随机整数(背下来就可以了):
属性、方法名 功能 Math.PI 圆周率 Math.floor() 向下取整 Math.ceil() 向上取整 Math.round() 四舍五入 就近取整 注意 -3.5 结果是 -3 Math.abs() 绝对值 Math.max() / Math.min() 求最大和最小值 Math.random() 获取范围在[0,1)内的随机值,含0不含1 function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } // 扩展: 随机点名 var arr = ['茶', '御茶', '茶茶子', '夏小朋友', '鲜柠芦荟茶', '特特给我背锅']; // 令数组下标是个随机数就可以了 console.log(arr[getRandom(0, arr.length - 1)]);
- 寻找最大值、绝对值、取整:
console.log(Math.max(1, 99, '一只比特')); // NaN console.log(Math.max()); // -Infinity // 1.绝对值方法 Math.abs() console.log(Math.abs(-1)); // 1 console.log(Math.abs('-1')); // 隐式转换 会把字符串型 -1 转换为数字型 console.log(Math.abs('Tea')); // NaN // 2.三个取整方法 // (1) Math.floor() 地板 向下取整 往最小了取值 console.log(Math.floor(1.1)); // 1 console.log(Math.floor(1.9)); // 1 // (2) Math.ceil() ceil 天花板 向上取整 往最大了取值 console.log(Math.ceil(1.1)); // 2 console.log(Math.ceil(1.9)); // 2 // (3) Math.round() 四舍五入 其他数字都是四舍五入,但是 .5 特殊 它往大了取 console.log(Math.round(1.5)); // 2 console.log(Math.round(-1.5)); // 这个结果是 -1 ∵取大的 -1 > -2
3.日期对象(是构造函数)
- 需要实例化 Date(使用 new) 才可以调用里面的属性方法。
var now = new Date(); // 没有参数 则获取当前时间 var date1 = new Date(2019, 10, 1); // 数字型写法 console.log(date1); // 返回的是 11月 不是 10月 var date2 = new Date('2019-10-1 8:8:8'); // 字符串型写法 console.log(date2);
- 格式化 年月日:
// 2020年 3月 21日 星期六 var date = new Date(); // 别忘记 实例化 Date() var year = date.getFullYear(); // 返回当前日期的年 2020 var month = date.getMonth() + 1; // 返回的月份小1个月 月份+1!! var dates = date.getDate(); // 返回的是 几号 var day = date.getDay(); // 周一返回的是 1 周六返回的是 6 但是 周日返回的是 0 var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']; // 将 周几 作为数组索引号 实现 数字到汉字 的转换 console.log('今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day]);
- 格式化 时分秒:
// 封装一个函数返回当前的时分秒 格式 08:08:08 function getTimer() { var time = new Date(); // 别忘记 实例化 Date() var h = time.getHours(); // 时 h = h < 10 ? '0' + h : h; // 利用三元表达式 在时间不是两位数时 补0 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(getTimer());
- 总毫秒数的含义:基于1970年1月1日(世界标准时间)起的毫秒数。
- 获取总毫秒数(时间戳):
var now = new Date(); // 实例化Date对象 console.log(date.valueOf()) // 1. 用于获取对象的原始值 console.log(date.getTime()) // 1. 用于获取对象的原始值 var now = +new Date(); // 2. 简单写可以这么做(最常用写法) +new Date() var now = Date.now(); // 3. HTML5 中提供的方法,有兼容性问题
- 倒计时效果 (原理:时间戳、时间格式化):
// 1.核心算法:输入的时间减去现在的时间就是剩余的时间,即倒计时 // 2.用时间戳来做:用户输入时间总的毫秒数减去现在时间的总的毫秒数 // 3.剩余时间总毫秒数 转换为天、时、分、秒 (时间戳转换为时分秒) function countDown(time) { var nowTime = +new Date(); // 当前时间总的毫秒数 var inputTime = +new Date(time); // 用户输入时间总的毫秒数 var times = (inputTime - nowTime) / 1000; // 剩余时间总的秒数 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('2020-3-22 18:00:00'));
4.数组对象
4.1 创建数组对象的两种方式
4.1.1 字面量方式
var arr = [1,"茶茶子",true];
4.1.2 new Array()
var arr0 = new Array(); // 创建了一个空的数组 var arr1 = new Array(2); // 这个2 表示 数组的长度为 2 里面有2个空的数组元素 var arr2 = new Array(2, 3); // 等价于 [2,3] 这样写表示 里面有2个数组元素 是 2和3
4.2 检测是否是数组
4.2.1 instanceof 运算符:可以用来检测是否为数组。
var arr = [1, 23]; var obj = {}; console.log(arr instanceof Array); // true console.log(obj instanceof Array); // false
4.2.2 Array.isArray():判断一个对象是否为数组,H5 新增的方法 IE9 以上版本支持。
var arr = [1, 23]; var obj = {}; console.log(Array.isArray(arr)); // true console.log(Array.isArray(obj)); // false
4.3 添加删除数组元素的方法
- push(后)、unshift(前) 为 增加 元素方法。
- pop(后)、shift(前) 为 删除 元素的方法。
// 1. push() 在数组的末尾 添加一个或者多个数组元素 // push 完毕之后,返回的结果是 新数组的长度 var arr = [1, 2, 3]; console.log(arr.push(4, 'tea')); // 2. unshift() 在数组的开头 添加一个或者多个数组元素 // unshift 完毕之后,返回的结果是 新数组的长度 console.log(arr.unshift('red', 'purple')); // 3. pop() 删除数组的最后一个元素 一次只能删除一个 没有参数 // pop 完毕之后,返回的结果是 删除的那个元素 console.log(arr.pop()); // 4. shift() 删除数组的第一个元素 一次只能删除一个 没有参数 // shift 完毕之后,返回的结果是 删除的那个元素 console.log(arr.shift());
4.4 数组排序(翻转+排序)
- sort()方法需要传入参数来设置升序、降序排序。
- 如果传入“function(a,b){ return a-b;}”,则为升序。
- 如果传入“function(a,b){ return b-a;}”,则为降序。
// 1. 翻转数组 var arr = ['pink', 'red', 'blue']; arr.reverse(); console.log(arr); // 2. 数组排序(冒泡排序) var arr1 = [13, 4, 77, 1, 7]; arr1.sort(function(a, b) { // return a - b; 升序的顺序排列 return b - a; // 降序的顺序排列 }); console.log(arr1);
4.5 查找指定数组元素
- indexOf(数组元素):返回该数组元素的索引号,从 前面 开始查找。
- lastIndexOf(数组元素) :返回该数组元素的索引号,从 后面 开始查找。
- 只返回 第一个 满足条件的 索引号,如果找不到 数组元素,则返回的是 -1。
- 数组去重案例:
// ['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'] 要求去除数组中重复的元素。 // 1.目标: 把不重复的元素选取出来放到新数组中。 // 2.核心算法: 遍历旧数组,用旧数组去查询新数组,若该元素在新数组里没出现过,就添加,否则不添加。 // 3.利用 新数组.indexOf(数组元素) 如果返回时 - 1 就说明 新数组里面没有该元素。 // 封装一个 去重的函数 unique 独一无二的 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(['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b']) console.log(demo);
4.6 数组转换为字符串
toString():将数组转化为字符串;join():给数组添加指定分隔符。// 1. toString() 将我们的数组转换为字符串 var arr = [1, 2, 3]; console.log(arr.toString()); // 1,2,3 // 2. join(分隔符) var arr1 = ['green', 'blue', 'pink']; console.log(arr1.join()); // green,blue,pink console.log(arr1.join('-')); // green-blue-pink console.log(arr1.join('&')); // green&blue&pink
4.7 其他方法
5.字符串对象
5.1 基本包装类型
- 基本包装类型:把 简单数据类型 包装成为 复杂数据类型,这样 基本数据类型 就有了 属性和方法。
- 比如 String 作为简单数数据类型不应该有 length 属性,但实际上它有,因为被 js 包装了。
var temp = new String('Tea'); // 1. 生成临时变量,把简单类型包装为复杂数据类型 str = temp; // 2. 赋值给声明的字符变量 temp = null; // 3. 销毁临时变量
5.2 字符串的不可变
- 在内存中重新给字符串赋值,会重新在内存中开辟空间存新值,变量之前保存的旧值不会被修改,旧值仍占据原来的内存空间,这个特点就是字符串的不可变。
- 由于字符串的不可变,在 大量拼接字符串 的时候会有效率问题。
5.3 根据字符返回位置
// 字符串对象 根据字符返回位置 str.indexOf('要查找的字符', [起始的位置]) var str = '改革春风吹满地,春天来了'; console.log(str.indexOf('春')); console.log(str.indexOf('春', 3)); // 从索引号是 3的位置开始往后查找
- 查找字符串"abcoefoxyozzopp"中所有 o 出现的位置及次数:
var str = "oabcoefoxyozzopp"; var index = str.indexOf('o'); // 查找第一个o出现的位置索引 var num = 0; // 用于统计 o 个数 while (index !== -1) { // 只要存在 o(indexOf 返回的结果不是 -1 )就一直查找 console.log(index); // 打印 o 当前的位置索引 num++; index = str.indexOf('o', index + 1); // 当前索引加1,从而继续向后查找 } console.log('o 出现的次数是: ' + num);
5.4 根据位置返回字符(重点)
// 1. charAt(index) 根据位置返回字符 var str = 'TeaMeow'; console.log(str.charAt(3)); // M // 遍历所有的字符 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 新增的 console.log(str[0]); // a
- 判断一个字符串 'abcoefoxyozzopp' 中出现次数最多的字符,并统计其次数:
// 有一个对象 来判断是否有该属性 对象['属性名'] var o = { age: 18 } if (o['sex']) { console.log('里面有该属性'); } else { console.log('没有该属性'); } // 判断一个字符串 'abcoefoxyozzopp' 中出现次数最多的字符,并统计其次数。 // 核心算法:利用 charAt() 遍历这个字符串 // 遍历对象,得到最大值和该字符 var str = 'abcoefoxyozzopp'; var o = {}; // 创建了一个空对象 for (var i = 0; i < str.length; i++) { var chars = str.charAt(i); // chars 是字符串的每一个字符 if (o[chars]) { // o[chars] 得到的是属性值 o[chars]++; // 对象存在这个属性 属性出现次数就+1 } else { o[chars] = 1; // 对象不存在这个属性 属性出现次数就是1 } } console.log(o); // 2. 遍历对象 var max = 0; var ch = ''; for (var k in o) { if (o[k] > max) { max = o[k]; // o[k] 属性值 ch = k; // k 属性名 } } console.log(max); console.log('最多的字符是' + ch);
5.5 字符串操作方法(重点)
- 追加指定字符串:concat();
- 截取指定字符串:substr();
// 1. concat('字符串1','字符串2'....) 追加字符串 var str = 'Tea'; console.log(str.concat('red')); // Teared // 2. substr('截取的起始位置', '截取几个字符'); var str1 = '改革春风吹满地'; console.log(str1.substr(2, 2)); // 春风
- 替换指定字符串:replace();
- 把字符串转换成数组:split();
// 1. 替换字符 replace('被替换的字符', '替换为的字符') 它只会替换第一个字符 var str = 'andyandy'; console.log(str.replace('a', 'b')); // bndyandy // 有一个字符串 'abcoefoxyozzopp' 要求把里面所有的 o 替换为 * var str1 = 'abcoefoxyozzopp'; while (str1.indexOf('o') !== -1) { // 只要里面能查到字符 o str1 = str1.replace('o', '*'); // 就把字符 o 替换成 * } console.log(str1); // 2. 字符转换为数组 split('分隔符') 前面学过 join 把数组转换为字符串 var str2 = 'red, pink, blue'; console.log(str2.split(',')); var str3 = 'red&pink&blue'; console.log(str3.split('&'));
十四.JavaScript 简单数据类型和复杂数据类型
1.简单数据类型和复杂数据类型
1.1 简单类型(基本数据类型、值类型)
- 在存储时变量中存储的是值本身,包括string ,number,boolean,undefined,null。
存放在 栈 里面 里面直接开辟一个空间存放值。
var timer = null; console.log(typeof timer); // 简单数据类型 null 返回的是一个空的对象 object // 如果有个变量以后打算存储为对象,暂时没想好放啥, 这个时候就给 null
1.2 复杂数据类型(引用类型)
- 在存储时变量中存储的是地址(引用),通过 new 关键字创建的对象,如 Object、Array、Date 等。
首先在 栈 里面存放地址 十六进制表示 然后这个地址指向 堆 里面的数据。
2.堆栈
2.1 堆栈空间分配区别
- 栈:由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈。
- 堆:存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
- 简单数据类型的存储方式:值类型变量的数据直接存放在变量(栈空间)中。
- 复杂数据类型的存储方式: 引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中。
3.简单数据类型传参
- 函数形参被传送 值类型的实参 时,其实是把变量在 栈 里的值 复制 了一份给形参。
- 在方法内部对形参做任何修改,都不会影响到的外部变量。
function fn(a) { a++; console.log(a); } var x = 10; fn(x); console.log(x); // 10
4.复杂数据类型传参
- 函数形参被传送 对象类型的实参 时,其实是把变量在 栈 里保存的 堆地址 复制给了形参。
- 形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象,会互相影响。
function Person(name) { this.name = name; } function f1(x) { // x = p 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. 这个输出什么 ? 狗比特