https://www.bilibili.com/video/BV14y4y1q754?p=4&spm_id_from=pageDriver
目录
一。js基础
第一节——了解js
1.js在网页的作用
js表示行为
2.js的三大核心
-
ECMAScript
语法(也可以说是js的规则)
-
BOM(Browser Object Model)
操作浏览器的属性和方法(例如滚动条,回退,前进按钮)
-
DOM(Document Object Model)
文档操作(通过操作js改变文档流,例如绑定id来进行一个点击事件,改变部分html内容)
第二节——js书写
-
行内式
-
a标签
a标签本身就有跳转的行为
为了区分 会先写个JavaScript:在写js代码
-
非a标签
-
-
内嵌式
-
外链式
第四节——js的输出语法
-
console.log()
输出到控制台
-
document.write()
输出到页面,可以解析标签(例如br 换行)
-
alert()
弹窗提示
第五节——js的变量
-
什么是变量
在一段程序的运行中,保存一个中间件使用的(例如 Π 圆周率)
我的理解:记录一些大的 复杂的值赋给一个你自己定义的值,方便调用。
-
js定义变量
-
语法
var 变量名 = 值
-
特点
一个变量只能保存一个值(第二个值会覆盖原来的值)
不使用var定义则为弱类型
-
命名规则
不能以数字开头 只能使用(a-z,A-Z, _ 和$两个特殊符号)
不能使用关键字 和保留字
-
规范
不要使用中文命名
使用驼峰命名法(第二个单词开始,首字母大写)
尽量语义化(通俗易懂的单词)
-
二。数据类型转换
第十二节——js数据类型转换_转数值
-
其他类型转数值类型
-
Number()
将转换的类型当作一个整体,如果存在非数字则返回结果为NaN
-
parseInt()
将要转换的数据一个一个进行转换,如果遇到非数字就停止转换,返回前面转换的值
不能识别小数点,遇到小数点会停止转换。
-
parseFloat()
跟parseInt规则一样,但是可以识别小数点
-
取正负号
通过给需要转换的数据添加正负号实现数值类型转换,但是负号会改变大小
-
非加号运算符
a * 1
a - 0
a / 1
使用加号 直接会拼接到一起
-
第十三节——js数据类型转换_转字符串
1.其他类型转字符串
-
String()
将需要转换的值放入String的()中
所有类型都可以转成字符串
-
toString()
将需要转换的值加上 .toString()
null和undefined不能转换
Uncaught TypeError: Cannot read property 'toString' of undefined 你的代码里肯定有xxx.yyyy 报错是以为xxx是undefined Uncaught TypeError: Cannot read property 'toString' of null 你的代码里肯定有xxx.yyyy 报错是以为xxx是unll
-
加法运算(加号(+)有两个意义)
-
字符串拼接
符号一边为字符串,就会进行字符串拼接
-
进行数学运算
只有两边都是数字类型或者布尔类型才会进行数学运算
-
第十四节——js数据类型转换_转布尔
1.其他类型转布尔
-
Boolean()
在js里只有五个内容会被转换为false
-
null
-
undefined
-
''
-
NaN
-
0
其他都为true
-
console.log(Boolean([] == 0)) 结果为true
console.log(Boolean([] == '')) 结果为true
三。运算符
第十五节——运算符_数学运算符
1.数学运算符
-
+
-
字符串相加
-
数字相加
-
-
-
-
*
-
/
-
%
求余
-
**
取幂
console.log(2 ** 10) 结果 2014
第十六节——运算符_赋值运算符
1.赋值运算符
-
=
从右向左执行赋值
-
+=
a = a + b 等价于 a += b 下面类似
-
-=
-
*=
-
%=
-
**=
-
/=
第十七节——运算符_比较运算符
1.比较运算符
-
.>
对两个数比较 返回结果为true或者false
-
<
-
.>=
-
<=
-
==
判断两个数的值是否相等,不判断数据类型
-
===
值和数据类型都判断
-
!=
-
!==
第十八节——运算符_逻辑运算符
1.逻辑运算符
-
&& 与(且)
两边为true才为true
-
|| 或
-
!非
第十九节——运算符_自增自减运算符
1.自增自减运算符
-
一元运算符
一元:一个符号带一个变量就可以运算
-
++
++n 和 n++都会改变n的值
++n 返回(n+1)的值 n--返回(n)的值
var n = 10 console.log(n++) 结果是 10 var a = 10 console.log(++a) 结果是 11 var b = 5 console.log(n++ + ++n + ++n + n++) 结果是 5+7+8+8=28 console.log(n) 结果是 9
-
--
四。循环语句
第二十节——条件分支语句
-
条件分支语句
-
if
-
if(){
}else(){}
-
if(){
}else if(){
}else{
}
// 判断1-2020年那几年是闰年 // 思路 :先进行一个循环判断 // 在里面判断是否为闰年 for(var n = 1; n < 2020; n++){ if(n % 4 === 0 && n % 100 !== 0 || n % 400 === 0){ console.log(n+'年是闰年') } }
-
-
switch
-
语法
-
switch(判断的语句){ case 情况一: 结果一 break; default: 其他不符合的结果 }
-
注意点
-
case和判断的变量值和类型都相同(===)才能满足
-
只能判断一个字面值,不能判断范围(数据多避免使用)
-
break结束执行,不写 会输出下一个结果 不写break会一直执行下去,直到代码结束(不管是否满足case)
-
default 类似与 if 里的 else
-
//根据输出的月份显示天数 var month = 4 switch(month){ case 1: case 3: case 5: case 7: case 8: case 10: case 12: console.log('31天') break; case 4: case 6: case 9: case 11: console.log('30天') break; case 2: console.log('28') break; }
-
-
第二十六节——while循环语句
-
语法
var n = 1
while(条件){
重复执行的代码
n = n + 1
}
var count = 0 var n = 1 while(n <= 10){ count = count + n n++ } console.log(count) 结果 55 // 6的阶乘 var sum = 1 var a = 6 while(a >= 1){ sum *= a a-- } console.log(sum) 结果 720
第二十七节——do while循环语句
-
语法
do{
要重复执行的代码
}while(条件)
-
与while循环的区别
-
不管条件是否成立,都执行一遍
-
只要在第一次条件不成立的情况下才有区别
-
var text = prompt('哇哇哇哇')
while(text !== 'wuyuetian' ){
text = prompt('哇哇哇哇')
}
do{
var text = prompt('哇哇哇哇')
}while(text !== 'wuyuetian')
第二十八节——for循环语句
-
语法
for( i = 0; i < 10; i++ ){
重复执行的代码
}
for( i = 0; i < 10; i++ ){
console.log('123')
}
// 输出一个直角三角形
// 思路 一个循环输出列 一个循环输出行
// 行的的长度应该小于等于列
for(var i = 1; i < 9; i++){
console.log(i)
for(var j = 1 ; j <= i; j++ ){
document.write('*')
}
document.write('<br>')
}
*
**
***
****
*****
******
*******
********
for(var i = 1; i < 9; i++){
console.log(i)
for(var j = 8 ; j >= i; j-- ){
// document.write(' ')
document.write('*')
}
document.write('<br>')
}
********
*******
******
*****
****
***
**
*
for(var i = 1; i < 9; i++){
console.log(i)
for(k = 1; k < i; k++){
document.write(' ')
}
for(var j = 8 ; j >= i; j-- ){
// document.write(' ')
document.write('*')
}
document.write('<br>')
}
********
*******
******
*****
****
***
**
*
// 求最大公约数
// 思路:一到小的数 是否有数满足 两个数除以那个数余数为0 大的数覆盖小的数
// 或者小的数到一 是否有数满足 两个数除以那个数余数为0(如果余数不为一 就使用下面的方法)
// 先设定两个数
var a = 2
var b = 10
// 对两个数比较,如果b大于a 则交换两个数的值
if(a < b){
var dep = a
a = b
b = dep
// console.log( a , b )
// 循环输出3到1
for(var i = b; i >= 1; i--){
// 进行判断
if(a % i === 0 && b % i === 0){
console.log('最大公约数为:' + i)
break
}
}
} 结果:最大公约数为:2
// 辗转相除法
// m = 16 n = 6
// 16 % 6 不能整除(m % n)
// 6 % 4 n / (m % n) 不能整除
// 4 % 2 能整除
// 能被整除就跳出循环 使用while
// 先判断两个数的大小
var m = 10
var n = 4
if(m < n){
var dep = n
n = m
m = dep
}
while(m % n !== 0){
// 不能整除就把n 的值赋值给 m (m % n)的值赋值给n
var temp = m % n
m = n
n = temp
}
console.log('最大公约数为:' + n)
结果:最大公约数为:2
// 最小公倍数(能整除两个数的最小数,最大不会超过两个数的乘积)
// 使用for循环 从大的数循环到两个数的乘积 循环为大的数倍数
var m = 4
var n = 32
// 先判断大小
if(m < n){
var temp = m
m = n
n = temp
}
for(var i = m ; i <= (m * n); i += m ){
if(i % m === 0 && i % n === 0){
break
}
}
console.log('最小公倍数:' + i) 结果:最小公倍数:32
// while循环 当 i 既能 整除 m 也能整除 n 的时候跳出循环
var m = 2
var n = 12
if(m < n){
var temp = m
m = n
n = temp
}
var i = m
while( i % n !== 0 || i % m !== 0){
i += m
}
console.log('最小公倍数:' + i) 结果:最小公倍数:12
// 打印1000-2000的闰年,隔四个打印一排
var count = 0
// 打印1000-2000
for(var i = 1000; i <= 2000; i++){
// 判断是否为闰年
if(i % 4 === 0 && i % 100 !== 0 || i % 400 ==- 0){
document.write(i + ' ')
count++
// 判断一行的个数
if(count % 4 === 0){
document.write('<br>')
}
}
}
五。函数
第四十二节——了解函数
-
函数
一种复杂数据类型
-
语法
function 函数名() {}
-
声明式函数
-
function fn(){ console.log('wuyuetian') }
-
赋值式函数
-
var fun = function(){ console.log('wuyuetian') }
-
第四十三节——函数的参数
-
形参
写在()里的 只能在函数内使用的变量
-
实参
是一个准确的值,为了给形参数赋值
-
函数参数的个数关系
-
一样多
从左到右一一对应
-
实参多
不会报错,多的实参不会显示
-
形参多
多的形参没有实参可以赋值,会显示undefined
function fn(a,b,c){ console.log(a,b,c) } fn(10,20) 结果:10 20 undefined
-
第四十五节——arguments
-
arguments
在函数内部自带的变量
表示所有实参的集合(伪数组)
-
属性
-
length
表示你的函数调用了多少个实参
-
-
排列
序号从0开始依次排列
序号又被叫为索引或者下标
function fn(){
var sum = 0
for(var i = 0; i < arguments.length; i++){
// console.log(arguments[i])
sum += arguments[i]
}
console.log(sum)
}
fn(10,20,30,40,50) 结果:150
第四十六节——函数的返回值
return
-
把计算结果返回,返回出去的内容,不是这个变量,是这个变量代表的值
function fn(){
var sum = 0
for(var i = 0; i < arguments.length; i++){
// console.log(arguments[i])
sum += arguments[i]
}
return sum
}
var res = fn(10,20,30,40,50)
console.log(fn(20,40))
alert(res)
document.write(fn(10,30))
-
return的作用
除了可以作为一个返回值关键字来使用
也可以进行打断函数的操作
第四十七节——封装代码
/**
* 求最大公约数
* @param {Number} a 第一格数字
* @param {Number} b 第二个数字
* @return {Number} 两个数字的最大公约数
*/
function getGys(a,b){
if(a < b){
var temp = b
b = a
a = temp
}
while( a % b !== 0){
var temp = a % b
a = b
b = temp
}
return b
}
/**
* 求最小公倍数
* @param {Number} a 第一格数字
* @param {Number} b 第二个数字
* @return {Number} 两个数字的最小公倍数
*/
function getGbs(a,b){
var res = getGys(a,b)
var bgs = a * b / res
return bgs
}
//质数
function zs(n){
flag = true
for(var i = 2; i < parseInt(n / 2); i++){
if(n % i === 0){
flag = false
break
}
}
return flag
}
// 求10到30的质数
for(var i = 10; i <= 30; i++){
var res = zs(i)
if(res){
console.log(i)
}
}
11
13
17
19
23
29
第四十九节——递归函数
-
本质
-
一个函数自己调用自己,当达到设置的终点时,再使用return归回来
-
-
注意
尽量少用递归,能用循环解决就用循环解决,递归最后考虑
// 递归求一个数的阶乘
function fn(n){
// n就是要求的阶乘
if(n === 1){
// 终点
return 1
}
return n * fn(n - 1)
}
var res = fn(6)
console.log(res) 结果:720
// 斐波那契数列 求第n位是多少
// 1 1 2 3 5 8 13 21 34 55 、、、
// 第一位和第二位都是固定的1
// 第三位开始依次是前两位的和
function fn(n){
if(n === 1 || n === 2){
return 1
}
return fn(n - 2) + fn(n - 1)
}
var res = fn(10)
console.log(res) 结果:55
// 递归求最大公约数
// 思路 终点 a % b === 0
// 没到终点 fn( b , a % b)
function fn(a,b){
// 判断a,b大小
if(a < b){
var temp = a
a = b
b = temp
}
if(a % b === 0){
return b
}
return fn(b , a % b)
}
var res = fn(4,6)
console.log(res) 结果:2
第五十节——函数和元素结合
-
语法
元素.onclick = 函数
-
书写方式
-
直接书写匿名函数
元素.onclick = 函数
-
给事件赋值一个具名函数
元素.onclick = 函数名
注意:函数名后面没有()
-
<input id="first" type="text"> +
<input id="second" type="text">
<button id="btn">=</button>
<input id="third" type="text" disabled>
//计算两个input的值
btn.onclick = function(){
// 获取的value值都为字符串类型
var a = first.value - 0
var b = second.value - 0
third.value = a + b
}
六。预解析(js被人诟病的缺点)
第五十五节——预解析
-
定义
在代码执行前,对代码进行检测
-
作用
-
会把 var 关键词定义的变量在代码执行声明
-
声明式函数所在的代码会先进行声明,并且赋值为一个函数,防止出现函数不存在的报错问题
-
赋值式函数会按照var的规则执行,如果调用函数方法,后写函数内容会报错
-
函数 和 变量 重名,以函数为准
fn() var fn = 100 fn() function fn() { console.log(123) } fn() 结果:在第二个fn()报错 TypeError: fn is not a function
-
-
无节操性
-
if条件无论是否运行,都会进行预解析
-
console.log(num) if(false){ var num = 100 } console.log(num) 结果:undefined undefined
-
return后面的代码不运行也会进行预解析
-
function fn() { var num1 = 100 console.log(num1) console.log(n) return var n = 100 } fn() 结果:100 undefined
-
七。作用域(js被人诟病的缺点)
第六十节——作用域
-
作用域
变量生效的范围
-
类型
-
全局作用域
打开一个页面就是一个全局作用域,也叫window
-
私有作用域
只有函数有私有作用域
一个函数有一个私有作用域
-
-
上下级关系(确定变量的使用范围)
-
三个机制
-
变量定义机制
有var关键词(var num)
有声明式函数(function fn() {} )
-
变量使用机制
需要获取一个变量来使用
n++
console.log( n )
-
变量赋值机制
要有赋值符号
num = 10
num += 10
-
-
-
变量定义机制
一个变量或者函数只能定义在一个作用域下,
只有本作用域和它下级的作用域可以使用
上一级不能使用
//下级调用上级 var a = 100 function fn() { console.log(a) } fn() 结果:100 //上级调用下级 function fn() { var a = 100 } fn() console.log(a) 结果:ReferenceError: a is not defined
-
变量使用机制
使用一个变量时先在自己的作用域找,找不到再去上一级作用域,
如果找不到则会报错
//自己作用域有就调用自己的 var a =100 function fn() { var a = 200 console.log(a) } fn() 结果:200 //自己作用域没有调用上一级 var a =100 function fn() { // var a = 200 console.log(a) } fn() 结果 100 //形参相当于函数内部定义的私有变量 var a = 100 function fn(a) { console.log(a) } fn() 结果:undefined //找不到报错 function fn() { console.log(a) } fn() 结果;ReferenceError: a is not defined
-
变量赋值机制
给一个变量赋值时,先在先在自己的作用域找,找不到再去上一级作用域
找到window都没有,则赋值给window
//向上赋值 function fn() { // 声明私有变量 num ,只能在fn 内部使用,fn 外不能用 // var num = 100 num = 200 console.log(num) } fn() console.log(num) 结果:200 200 var a function fn() { var a function fun() { a = 200 } console.log(a) //undefined fun() console.log(a) // 200 } console.log('上:' + a) // undefined fn() console.log('下;' + a) // undefined
第六十二节——作用域与预解析
fn()
var fn = 100
function fn() {
fn = 200
}
console.log(fn) //100
// 1.fn() fn = 200 定义为全局变量
// 2.var fn = 100 全局变量fn 值为100
// 3.console.log(fn) 输出的值为100
fn()
fn() //报错 fn is not a function
var fn = 100
function fn() {
fn = 200
}
console.log(fn)
// 1.fn() fn = 200 定义为全局变量
// 2.fn() fn 是一个值,不是函数 会报错
function fn() {
var num = 100
function fun() {
var num = num
console.log(num) //undefined
}
fun()
}
fn()
第六十三节——作用域里面的预解析
-
全局预解析
页面打开就会进行
-
私有作用域解析
函数内部的预解析只属于函数内部
-
问题
函数的形参和定义的私有变量重名
先进行形参赋值,后进行预解析
var a = 100 function fn(b) { function b() {console.log(213)} b() } fn(300) //结果:213
// 计数器
var sum = 0
and.onclick = function () {
sum++
console.log(sum)
}
sub.onclick = function () {
sum--
console.log(sum)
}
八。数据类型
第六十五节——了解对象数据类型
-
对象数据类型
一种复杂的数据类型,
一个盒子承载一堆数据
-
创建方式
-
字面量创建
var n = {} var m = {} console.log(m)
-
内置构造函数创建
var n = new Object() var m2 = new Object() console.log(m2)
-
-
创建方式的区别
-
字面量创建可以直接添加键值对(key:value)的方式添加
var n = { name:'张三', //属性 tel:123, fn: function () { //方法 console.log('五月天') } } console.log(n)
-
内置构造函数创建通过操作语法来进行增删改查
var n = new Object() console.log(n) //{} // 添加 n.age = 18 n.name = 'zhangsan' console.log(n) //{age: 18, name: "zhangsan"} console.table(n) // 删除 delete n.name console.log(n) // {age: 18} // 修改 n.age = 20 console.log(n) // {age: 20} // 查询 console.log(n.age) // 20
数组关联语法
var m = {} // 添加 m['name'] = 'zhangsan' m['age'] = 19 console.log(m) //{name: "zhangsan", age: 19} // 删除 delete m['name'] console.log(m) //{age: 19} // 修改 m['age'] = 20 console.log(m) //{age: 20} // 查询 console.log(m['age']) //20
-
操作方法
点语法
-
两种操作语法的区别
点语法 不能拼接字符串 不能使用变量
数组关联语法 可以使用变量,可以拼接字符串
当括号里面是一个变量时,会把变量的值当作属性名称
-
-
var obj = {} var name = 'wuyuetian' obj[name] = '123' console.log(obj) //{wuyuetian: "123"}
-
第六十八节——循环遍历对象
-
遍历对象
-
for in循环
语法:
for(var 变量 in 对象) {
重复执行的代码
}
var objs = { name: 'wuyuetian', age: '18', scroe: '20', height: '190' } for(var key in objs ) { console.log(key) console.log(objs[key]) } // name // wuyuetian // age // 18 // scroe // 20 // height // 190
-
判断一个成员是不是在这个对象里
-
成员名 in 对象名(成员名需要使用字符串)
-
var objs = { name: 'wuyuetian', age: '18', scroe: '20', height: '190' } console.log('name' in objs) //true
-
-
扩展
window 的 name属性
作用:在iframe 标签 和 name 属性合作进行跨域的
特点:被固定为字符串类型
-
第六十九节——数据类型存储上的区别
-
基本数据类型和复杂数据类型的区别
-
基本数据类型
Number 数值
String 字符串
Undefined 空
Null 空
Boolean 布尔
-
复杂数据类型
Object 对象
Function 函数
浏览器的一段存储空间
-
栈内存
存储方式是先来的在栈底
简单数据类型存储在栈内存中
-
堆内存
存储方式是随机存储
复杂数据类型将值存储在堆内存中(有一个对象空间),值的地址存储在栈内存中
-
第七十节——数据类型存储上的区别
-
数据类型赋值的区别
-
基本数据类型
-
把变量存储的值赋值给另一个变量
-
就像复制粘贴,不影响原来的值
-
-
复杂数据类型
-
复杂数据类型存储的是地址,将变量赋值,就是把地址给了另一个变量
-
两个变量就操作一个数据
-
var obj = { name: 'wuyuetian', age: 19 } var obj2 = obj //改变obj地址中的数据 obj['age'] = 20 //通过obj2查看 console.log(obj2) //{name: "wuyuetian", age: 20}
-
-
函数形参和实参的关系
实参实在函数调用是对形参进行赋值
function fn(a,b) { // 形参a 与全局 num 没有关系 a = 100 // 形参b和全局obj指向同一个对象空间, // 修改数据,全局的数据也被修改 b.age = 20 } var num = 200 var obj = { name: 'wuyuetian', age: 18 } fn(num,obj) console.log(num) //200 console.log(obj) //{name: "wuyuetian", age: 20}
-
函数的返回值也是变量赋值的一种
接收的就是函数里面定义的对象地址
-
第七十一节——函数也是一个对象
-
函数也是一个对象
-
函数的存储空间分为两块
-
一边放形参和代码
-
另一边存储数据
-
-
函数的两个功能
-
函数名()
把函数当作一个函数来执行
-
函数名.成员名 = '值'
存储一些数据
-
两个功能互不干扰
-
-
第七十二节——数组数据类型
-
数组数据类型
-
复杂数据类型 Array
-
按照序号排列来存储数据(序号从零开始)
-
-
数组的创建
-
字面量创建
var arr = []
-
内置构造函数创建
var arr = new Array()
-
-
字面量创建直接添加数据
var arr = [10,20,30,40] console.log(arr) //(4) [10, 20, 30, 40]
-
内置构造函数直接添加数据
-
不传递参数(空数组)
var arr = new Array() console.log(arr) //[]
-
传递一个参数(表示数组的长度)
var arr = new Array(2) console.log(arr) //(2) [空 ×2]
-
传递多个参数
var arr = new Array(2,20,30) console.log(arr) // (3) [2, 20, 30]
-
-
数组的操作
-
length属性
读:获取数组的长度
写:设置数组的长度
当设置的长度比本身长,缺少的用空值代替
var arr = [10,20,30,40] arr.length = 5 console.log(arr) //(5) [10, 20, 30, 40, 空]
当设置的长度比本身短,多余的则删除
var arr = [10,20,30,40] arr.length = 3 console.log(arr) //(3) [10, 20, 30]
-
索引
-
读:读取指定位置的数据,没有则显示undefined(读取的是序号)
var arr = [10,20,30,40] console.log(arr[1]) //20 console.log(arr[8]) //undefined
-
写:索引不存在则中间空值补齐,存在则替换原来的值
var arr = [10,20,30,40] arr[10] = 20 console.log(arr) //(11) [10, 20, 30, 40, 空 ×6, 20] var arr = [10,20,30,40] arr[3] = 20 console.log(arr) //(4) [10, 20, 30, 20]
-
数组的遍历
-
for循环
var arr = [10, 20, 30, 40] for (var i = 0; i < arr.length; i++) { console.log(arr[i]) } // 10 // 20 // 30 // 40
-
数组也是一个对象,可以使用for in 循环
var arrs = [10, 20, 30, 40] for (var arr in arrs) { console.log(arrs[arr]) } // 10 // 20 // 30 // 40
当成对象使用,可以使用点语法,也可以使用数组关联语法
添加的成员不占用length的位置(一般不用数组当作对象使用)
var arrs = [10, 20, 30, 40] arrs.name = 'wuyuetian' arrs['age'] = 20 console.log(arrs) //(4) [10, 20, 30, 40, name: "wuyuetian", age: 20]
-
-