JavaScript学习笔记二(26-50)
A-6-2 do while
循环
- 他是一个和while相似的循环6+
- while会进行条件判断,符合就执行,反之就不执行
- 但是
do while
循环不管条件,先执行一会,然后在开始进行条件判断 - 语法:
do{ 需要执行的代码 } while ( 条件 )
var num = 10
do {
consle.log('执行A')
num = num + 1
} while (num < 10)
do while
案例一:累加
案例一:1~100 累加
var n = 1
var sum = 0
do {
sum+=n
n++
} while (n<=100)
console.log(sum)
5050
do while
案例二:输入文本
do {
var re = prompt("请输入你的名字")
// console.log(res)
if (res) {
document.write(res)
}
} while (!res)
注意:prompt与alert类似,但是可以输入文本
A-6-3 for
循环
- 和
while
和do while
循环都不大一样的循环 - 道理和其他两种一样,都是循环执行代码的
- 语法:
for (var i = 0; i < 10; i++) { 需要执行的代码 }
//把初始化、条件判断、自身改变都卸载了一起
for (var i = 0; i < 10; i++) {
//这里输入需要执行的代码
console.log(i)
}
//控制台会依次输出 1 ~ 10
for
循环 案例1
for(var n = 1; n<=10; n++){
if (n<=3) {
console.log("广告商品",n)
} else {
console.log("普通商品",n)
}
}
**for
案例一
Q:1000-2000之中的闰年
提示:inputYear%400===0 || inputYear%4===0 && inputYear%100!==0
A1:
for(var n=1000; n<=2000; n++){
if(n%400===0 || n%4===0 && n%100!==0) {
doucument.write(n)
}
}
A2:
for(var n=1000; n<=2000; n+=4){
if(n%400===0 || n%100!==0) {
doucument.write(n+" ")
}
}
A3:
for(var n=1000; n<=2000; n+=4){
if(n%400===0 || n%100!==0) {
doucument.write(n+" ")
count++
if (count%4===0){
document.write("<br/>")
}
}
}
A-6-4 循环控制语句
- break终止循环
在循环没有进行完毕的时候,因为我设置的条件满足,提前终止循环。
例如:我要吃五个包子,但是吃到三个的时候饱了,我就停止吃包子的事情。
如果要终止循环,就可以直接使用break
关键字
for (var i = 1; i <= 5; i++){
//每循环一次,吃一个包子
console.log('我吃了一个包子')
//当i的值为3的时候,条件为true,执行{}内的代码终止循环
//循环终止,没有4和5
if (i === 3){
break
}
}
- continue 结束本次循环
在循环中,把循环的本次跳过,执行后续的循环
例如:吃五个包子,吃到第三个的时候包子掉地上了,跳过第三个吃第四和第五个
跳过本次循环,就可以使用continue
关键字
for (var i = 1; i <= 5; i++){
//每循环一次,吃一个包子
//{}内由continue,那么本次循环后面的代码都不执行了
//自动算作i 为 3 的这一次结束了,去执行i= 4 的那次循环
if (i === 3){
console.log('这是第三个包子,掉地上了')
continue
}
console.log('我吃了一个包子')
}
A-6-5 循环案例
案例一:求质数
九九乘法表
可以在document.write里加入span标签来控制每个格子的大小
A-7 函数
Function
是一个复杂数据类型
- 对于js来说,函数就是把任意一段代码放在一个盒子里面
- 在我想要让这段代码执行的时候,直接执行这个盒子里面的代码就行
for(vari=0;i<10;i++){
console. log(i)
}
//函数,这个{}就是那个“盒子”
function fn() {
//这个函数我们以前写的代码
for(vari=0;i<10;i++){
console. log(i)
}
}
A-7-1 定义函数
定义阶段就是我们把代码放在盒子里面。
我们就要学习怎么放进去,也就是书写一个函数。
我们有两种定义方式声明式和赋值式。
声明式
使用function这个关键字来声明一个函数
function fn(){
//一段代码
}
function
: 声明函数的关键字,表示接下来是一个函数了
fn
:函数的名字,我们自己定义的(遵循变量名的命名规则和命名规范)
()
: 必须写,是用来放参数的位置
{}
:就是我们用来放一段代码的位置(刚才说的“盒子”)
赋值式
和我们使用var关键字是一 个道理
首先使用 var定义一个变量, 把一个函数当作值直接赋值给这个变量就可以了
var fn = functTion () {
//一段代码
}
//不需要在function后面书写函数的名字了,因为在前面已经有了
A-7-2 调用函数
函数调用就是直接写函数名()就可以了
//声明式函数
function fn() {
console.1og('我是fn函数')
}
//调用函数
fn()
----------------------------------------------------
//赋值式函数
var fn2 = function () {
console.1og('我是fn2函数')
}
// 调用函数
fn()
注意:定义完一个函数以后,如果没有函数调用,那么写在{}里面的代码没有意义,只有调用后才会执行
调用的区别
虽然两种定义方式的调用都是一样的,但是还是有一些区别:
声明式函数:调用可以在定义之前或者定义之后
赋值式函数: 调用只能在 定义之后
A-7-3 函数的参数
我们在定义函数和调用函数的时候都出现过()
,
()
就是拿来放参数的容器
参数分为两种 形参 和 实参
基本形式:
//声明式
function fn(行参) {
// 一段代码
}
fn(实参)
//賦值式
var fn = function (行参) {
//一段代码
}
fn(实参)
形参
就是在函数内部可以使用的变量,在函数外部不能使用
每写一个单词,就相当于在函数内部定义了一个可以使用的变量(遵循变量名的命名规则和命名规范)
多个单词之间以 ,
分隔
function fn(num) {
// 代码
}
var fn1 = function (num) {
// 在函数内部就可以使用 num 这个变量
}
// 多个参数:
function fun(num1, num2) {
//代码
}
var fun1 = function (num1, num2) {
// 在函数内部就可以使用 num1 和 num2 这两个变量
}
如果只有行参的话,那么在函数内部使用的变量是没有值的,也就是 undefined
行参的值是在函数调用的时候由实参决定的
实参
在函数调用的时候给行参赋值的
也就是说,在调用的时候是给一个实际的内容的。
函数内部的行参的值,由函数调用的时候传递的实参决定
多个参数的时候,是按照顺序一一对应的
function fn(num) {
// 函数内部可以使用 num
}
fn(100)
// 这个函数的本次调用,书写的实参是 100
// 那么本次调用的时候函数内部的 num 就是 100
fn(200)
// 这个函数的本次调用,书写的实参是 200
// 那么本次调用的时候函数内部的 num 就是 200
参数个数的关系:
- 行参比实参少
因为是按照顺序一一对应的
行参少就会拿不到实参给的值,所以在函数内部就无法用到这个值。
function fn(num1, num2) {
}
fn(100, 200, 300)
这里num1对应100,num2对应200,但是300没有对应的形参,也就在函数内部无法使用300这个变量
- 行参比实参多
因为是按照顺序一一对应的
所以多出来的行参就是没有值的,就是undefined
A-7-4 函数的返回值和终断函数
函数调用本身也是一个表达式, 表达式就应该有一个值出现
现在的函数执行完毕之后,是不会有结果出现的
函数的return是返回的意思,其实就是给函数一个返回值和终断函数
// 比如 1 + 2 是一个表达式,那么 这个表达式的结果就是 3
console.log(1 + 2) // 3
function fn() {
// 执行代码
}
// fn() 也是一个表达式,这个表达式就没有结果出现
console.log(fn()) // undefined
-------------------------------------------------------------
function fn() {
// 执行代码
return 100
}
// 此时,fn() 这个表达式执行完毕之后就有结果出现了
console.log(fn()) // 100
终断函数:
当开始执行函数以后,函数内部的代码就会从上到下的依次执行
必须要等到函数内的代码执行完毕
而 return
关键字就是可以在函数中间的位置停掉,让后面的代码不在继续执行
function fn() {
console.log(1)
console.log(2)
console.log(3)
// 写了 return 以后,后面的 4 和 5 就不会继续执行了
return
console.log(4)
console.log(5)
}
// 函数调用
fn()
A-7-5 函数预解析
首先了解为什么要预解析
js 是一个解释型语言,就是在代码执行之前,先对代码进行通读和解释,然后在执行代码
也就是说, js 代码在运行的时候,会经历两个环节:解释代码和执行代码
解释代码:
因为是在所有代码执行之前进行解释,所以叫做 预解析(预解释)
需要解释的内容有两个
声明式函数:在内存中先声明有一个变量名是函数名,并且这个名字代表的内容是一个函数
var 关键字 在内存中先声明有一个变量名
fn()
console.log(num)
function fn() {
console.log(' fn 函数')
}
var num = 100
预解析后:
function fn() {
console.log('我是 fn 函数')
}
var num
fn()
console.log(num)
num = 100
赋值式函数会按照 var
关键字的规则进行预解析
A-8 作用域
就是一个变量可以生效的范围
变量不是在所有地方都可以使用的,而这个变量的使用范围就是作用域
A-8-1 全局作用域
全局作用域是最大的作用域
在全局作用域中定义的变量可以在任何地方使用
页面打开的时候,浏览器会自动生成一个全局作用域 window
这个作用域会一直存在,直到页面关闭就销毁
A-8-2 局部作用域
局部作用域就是在全局作用域下面有开辟出来的一个相对小一些的作用域
在局部作用域中定义的变量只能在这个局部作用域内部使用
在JS
中只有函数能生成一个局部作用域,别的都不行
每一个函数,都是一个局部作用域
A-8-3变量使用规则
有了作用域以后,变量就有了使用范围,也就有了使用规则
变量使用规则分为两种 访问规则和赋值规则
访问规则:
当想获取一个变量的值的时候,这个行为叫做访问
获取变量的规则:
首先,在自己的作用域内部查找
如果有,就直接拿来使用
如果没有,就去上一级作用域查找,如果有,就拿来使用
如果没有,就继续去上一级作用域查找,依次类推
如果一直到全局作用域都没有这个变量,那么就会直接报错(该变量is not defined
)
注意:变量的访问规则 也叫做 作用域的查找机制
作用域的查找机制只能是向上找,不能向下找
赋值规则:
当你想给一个变量赋值的时候,那么就先要找到这个变量,在给他赋值
变量赋值规则:
先在自己作用域内部查找,有就直接赋值
没有就去上一级作用域内部查找,有就直接赋值
还没有再去上一级作用域查找,有就直接赋值
如果一直找到全局作用域都没有,那么就把这个变量定义为全局变量,再给他赋值
function fn() {
num = 100
}
fn()
// fn 调用以后,要给 num 赋值
// 查看自己的作用域内部没有 num 变量
// 就会向上一级查找
// 上一级就是全局作用域,发现依旧没有
// 那么就会把 num 定义为全局的变量,并为其赋值
// 所以 fn() 以后,全局就有了一个变量叫做 num 并且值是 100
console.log(num) // 100
A-9 对象以及数据类型
对象是一个复杂数据类型 存储了一些基本数据类型的一个集合
数字num,字符串string,布尔值true
var obj = {
num: 100,
str: 'hello world',
boo: true
}
这里的 {}
和函数中的 {}
不一样
函数里面的是写代码的,而对象里面是写一些数据的
对象就是一个键值对的集合
{}
里面的每一个键都是一个成员
也就是说,可以把一些数据放在一个对象里面,那么他们就互不干扰了
其实就是准备一个房子,把想要的数据放进去,然后把房子的地址给到变量名,当需要某一个数据的时候,就可以根据变量名里面存储的地址找到对应的房子,然后去房子里面找到对应的数据
A-9-1 创建对象
字面量的方式创建对象
// 创建一个空对象
var obj = {}
// 像对象中添加成员
obj.name = 'Jack'
obj.age = 18
置构造函数的方式创建对象
// 创建一个空对象
var obj = new Object()
// 向对象中添加成员
obj.name = 'Rose'
obj.age = 20
A-9-2 数据类型
Object
是js内置的构造函数,用于创建一个对象使用的
数据类型之间存储的区别:
他们最大的区别就是在存储上的区别
存储空间分成两种栈和堆
栈: 主要存储基本数据类型的内容
堆: 主要存储复杂数据类型的内容
基本数据类型的存储:
var num = 100
,在内存中的存储情况
直接在 栈空间 内有存储一个数据
复杂数据类型在内存中的存储情况:
下面这个 对象 的存储
var obj = {
name: 'Jack',
age: 18,
gender: '男'
}
复杂数据类型的存储:
1.在堆里面开辟一个存储空间
2.把数据存储到存储空间内
3.把存储空间的地址赋值给栈里面的变量
这就是数据类型之间存储的区别
数据类型之间的比较:
1 基本数据类型是值之间的比较
var num = 1
var str = '1'
console.log(num == str) // true
2 复杂数据类型是地址之间的比较
var obj = { name: 'Jack' }
var obj2 = { name: 'Jack' }
console.log(obj == obj2) // false
注:因为创建了两个对象,那么就会在 堆空间 里面开辟两个存储空间存储数据(两个地址)
虽然存储的内容是一样的,那么也是两个存储空间,两个地址
复杂数据类型之间就是地址的比较,所以 obj 和 obj2 两个变量的地址不一样
所以得到的就是 false
A-10 数组
数组是一个数据的集合 也就是把一些数据放在一个盒子里面,按照顺序排好
[1, 2, 3, 'hello', true, false]
//这个东西就是一个数组,存储着一些数据的集合
数据类型分类:
number/string/boolean/undefined/null/object/function / array/ …
数组也是数据类型中的一种
简单的把所有数据类型分为两个大类:基本数据类型和复杂数据类型
基本数据类型: number / string / boolean / undefined / null
复杂数据类型: object / function / array / …
创建一个数组:数组就是一个[]
在[]
里面存储着各种各样的数据,按照顺序依次排好
字面量创建一个数组:
直接使用[]
的方式创建一个数组
// 创建一个空数组
var arr1 = []
// 创建一个有内容的数组
var arr2 = [1, 2, 3]
内置构造函数创建数组:
使用 js 的内置构造函数 Array 创建一个数组
// 创建一个空数组
var arr1 = new Array()
// 创建一个长度为 10 的数组
var arr2 = new Array(10)
// 创建一个有内容的数组
var arr3 = new Array(1, 2, 3)
A-10-1 数组的length
length: 长度的意思
length 就是表示数组的长度,数组里面有多少个成员,length 就是多少
// 创建一个数组
var arr = [1, 2, 3]
console.log(arr.length) // 3
A-10-2 数组的索引
索引,也叫做下标,是指一个数据在数组里面排在第几个的位置
注意: 在所有的语言里面,索引都是从 0 开始的
在 js 里面也一样,数组的索引从 0 开始
// 创建一个数组
var arr = ['hello', 'world']
上面这个数组中,第 0 个 数据就是字符串 hello,第 1 个 数据就是字符串 world
想获取数组中的第几个就使用 数组[索引] 来获取
var arr = ['hello', 'world']
console.log(arr[0]) // hello
console.log(arr[1]) // world
A-10-3 数组的排序
排序,就是把一个乱序的数组,通过处理,让他变成一个有序的数组
冒泡排序:
先遍历数组,让挨着的两个进行比较,如果前一个比后一个大,那么就把两个换个位置
数组遍历一遍以后,那么最后一个数字就是最大的那个了
然后进行第二遍的遍历,还是按照之前的规则,第二大的数字就会跑到倒数第二的位置
以此类推,最后就会按照顺序把数组排好了
首先准备一个乱序的数组
var arr = [3, 1, 5, 6, 4, 9, 7, 2, 8]
接下来就会用代码让数组排序
先不着急循环,先来看数组里面内容换个位置
// 假定现在要让数组中的第 0 项和第 1 项换个位置
// 需要借助第三个变量
var tmp = arr[0]
arr[0] = arr[1]
arr[1] = tmp
第一次遍历数组,把最大的放到最后面去
for (var i = 0; i < arr.length; i++) {
// 判断,如果数组中的当前一个比后一个大,那么两个交换一下位置
if (arr[i] > arr[i + 1]) {
var tmp = arr[i]
arr[i] = arr[i + 1]
arr[i + 1] = tmp
}
}
// 遍历完毕以后,数组就会变成 [3, 1, 5, 6, 4, 7, 2, 8, 9]
第一次结束以后,数组中的最后一个,就会是最大的那个数字
然后把上面的这段代码执行多次。数组有多少项就执行多少次
按照数组的长度来遍历多少次
for (var j = 0; j < arr.length; j++) {
for (var i = 0; i < arr.length; i++) {
// 判断,如果数组中的当前一个比后一个大,那么两个交换一下位置
if (arr[i] > arr[i + 1]) {
var tmp = arr[i]
arr[i] = arr[i + 1]
arr[i + 1] = tmp
}
}
}
// 结束以后,数组就排序好了
优化:
for (var j = 0; j < arr.length - 1; j++) {
for (var i = 0; i < arr.length; i++) {
// 判断,如果数组中的当前一个比后一个大,那么两个交换一下位置
if (arr[i] > arr[i + 1]) {
var tmp = arr[i]
arr[i] = arr[i + 1]
arr[i + 1] = tmp
}
}
}
第一次的时候,已经把最大的数字放在最后面了
那么第二次的时候,其实倒数第二个和最后一个就不用比了
因为要把倒数第二大的放在倒数第二的位置,即使比较了,也不会换位置
第三次就要倒数第三个数字就不用再和后两个比较了
以此类推,那么其实每次遍历的时候,就遍历 当前次数 - 1 次
for (var j = 0; j < arr.length - 1; j++) {
for (var i = 0; i < arr.length - 1 - j; i++) {
// 判断,如果数组中的当前一个比后一个大,那么两个交换一下位置
if (arr[i] > arr[i + 1]) {
var tmp = arr[i]
arr[i] = arr[i + 1]
arr[i + 1] = tmp
}
}
}
选择排序:
先假定数组中的第 0 个就是最小的数字的索引
然后遍历数组,只要有一个数字小,那么就替换之前记录的索引
知道数组遍历结束后,就能找到最小的那个索引,然后让最小的索引换到第 0 个的位置
再来第二趟遍历,假定第 1 个是最小的数字的索引
在遍历一次数组,找到小的那个数字的索引
遍历结束后换个位置
依次类推,也可以把数组排序好
准备一个数组
var arr = [3, 1, 5, 6, 4, 9, 7, 2, 8]
假定数组中的第 0 个是最小数字的索引
var minIndex = 0
遍历数组,判断,只要数字小,那么就替换掉原先记录的索引
var minIndex = 0
for (var i = 0; i < arr.length; i++) {
if (arr[i] < arr[minIndex]) {
minIndex = i
}
}
// 遍历结束后找到最小的索引
// 让第 minIndex 个和第 0 个交换
var tmp = arr[minIndex]
arr[minIndex] = arr[0]
arr[0] = tmp
按照数组的长度重复执行上面的代码
for (var j = 0; j < arr.length; j++) {
// 因为第一遍的时候假定第 0 个,第二遍的时候假定第 1 个
// 所以要假定第 j 个就行
var minIndex = j
// 因为之前已经把最小的放在最前面了,后面的循环就不需要判断前面的了
// 直接从 j + 1 开始
for (var i = j + 1; i < arr.length; i++) {
if (arr[i] < arr[minIndex]) {
minIndex = i
}
}
// 遍历结束后找到最小的索引
// 第一堂的时候是和第 0 个交换,第二趟的时候是和第 1 个交换
// 直接和第 j 个交换就行
var tmp = arr[minIndex]
arr[minIndex] = arr[j]
arr[j] = tmp
}
优化:和之前一样,倒数第二次排序完毕以后,就已经排好了,最后一次没有必要了
for (var j = 0; j < arr.length - 1; j++) {
var minIndex = j
for (var i = j + 1; i < arr.length; i++) {
if (arr[i] < arr[minIndex]) {
minIndex = i
}
}
var tmp = arr[minIndex]
arr[minIndex] = arr[j]
arr[j] = tmp
}
在交换变量之前,可以判断一下,如果遍历后得到的索引和当前的索引一直
那么就证明当前这个就是目前最小的,那么就没有必要交换
要判断,最小作引和当前作引不一样的时候,才交换
for (var j = 0; j < arr.length - 1; j++) {
var minIndex = j
for (var i = j + 1; i < arr.length; i++) {
if (arr[i] < arr[minIndex]) {
minIndex = i
}
}
if (minIndex !== j) {
var tmp = arr[minIndex]
arr[minIndex] = arr[j]
arr[j] = tmp
}
}