跳转b站黑马前端学习路线介绍
b站黑马js(pink)视频教程
github相关代码
稍有些python底子,此部分笔记代码不如html,css部分琐碎知识点多
alert("nihao,js")
document.write("标题
")
console.log('log检查')
prompt('qingshuru:')
变量-空间容器盒子
声明 let
let 变量名
赋值
变量名 = “值”
声明+赋值:变量初始化。注意要有空格
命名规则
关键字:let,if,var等不可用
_
,$
,字母,数字4种组成,数字不能开头
严格区分大小写,Age和age不同
命名规范
简明有意义
小驼峰命名:userName
var声明的特点(不建议用var,建议let声明)
1、可以先声明再使用:
console.log(num)
num=10
2、可以多次声明
3、变量提升,全局变量等问题
let arr = ["liu","li","zhang",10]
console.log(arr[2])
console.log(arr.length)
弱数据类型语言:不需要提前声明,赋值之后才确定数据类型
// 模板字符串 ``+${}
// 这里遇到一个小问题,因为我这些小例子代码写到一个文件里。前面的常量再次赋值那里有报错,导致同文件下方的此处代码不运行,注释掉前面的常量赋值就好了
let age = 18
console.log(`今年${age}岁了`)
boolean:true,false-布尔型字面量——字面量就是没有用标识符封装起来的量,是“值”的原始状态。
‘’、0、undefined、null、false、NaN的Boolean()测试后都为false,其余为true。
undefined:只声明,不赋值——弱数据类型,函数传参会用到
null:声明并且赋值了,值就为null,不太好理解,是一个代表”无“,”空“,”未知的“特殊值,一般作为尚未创建的obj对象。
引用数据类型
object 对象
tip:
nan——not a number
数据类型的检测
typeof()
数据类型的转换
prompt和表单获取的数据类型是string,计算时需要进行类型的检测和转换
1、隐式转换
+:自动的转换成可以支持的类型
2 + '2' = '22'
+ '123' = 123
-:
2 - '2' = 0
2、显示转换
Number(转换对象)
parseInt(保留整数,取整,不管是小数还是字符)
parseFloat(保留小数)
3、存储类型
借助堆栈概念(js里没有),简单数据类型存储是值,复杂数据类型存储的是地址(引用)
1、赋值运算符
=,+=,-=,%=等
2、一元运算符
+,-,++,–等
注意:
实际开发中,我们一般都是单独使用的,后置++ 更多;
前置++先进行+1,再进行运算;后置++,先进行运算,后进行+1
。"先运算,后进行+1"表述容易产生歧义,见代码:
3、逻辑运算符
与 | 或 | 非 |
---|---|---|
and | or | not |
&& | || | ! |
4、 比较运算符
> ,< 等
== 仅比较值是否相等
=== 是否全等
!== 不等
建议使用全等比较===
5、运算符优先级
优先级 | 运算符 | 顺序 |
---|---|---|
1 | 小括号 | () |
2 | 一元运算符 | ++,–,! |
3 | 算数运算符 | 先* / % 后+ - |
4 | 关系运算符 | > >= < <= |
5 | 相等运算符 | ==, !=, =, ! |
6 | 逻辑运算符 | 先 && 后 || |
7 | 赋值运算符 | = |
8 | 逗号运算符 | , |
1、顺序语句
2、分支语句
if条件,switch case
if ()里:除了0
的数字都为真,除了''
的字符串都为真
3、循环语句
while for
注意break,continue的位置与i++的位置逻辑
复习css阴影规则:
/* 向元素添加单个 box-shadow 效果时使用以下规则:
当给出两个、三个或四个 值时。
如果只给出两个值,那么这两个值将会被当作 来解释。
如果给出了第三个值,那么第三个值将会被当作解释。
如果给出了第四个值,那么第四个值将会被当作来解释。
可选,inset关键字。
可选,值。 */
box-shadow: 2px 2px rgba(44, 20, 196, 0.4);
push
,类比python的append
常用
arr.splice(,) :( 两个参数:操作的下标,删除的个数)let fn = function () {}
函数表达式必须先声明后使用,let 赋值类似也要先声明
2、立即执行函数
防止变量冲突,后边的定时器会用到
(function(){
let num = 10
})();
(function(x,y){
console.log(x + y)
})(1,2);
立即执行函数也可以应用在弹框
x = x || 0
类似于默认形参x = 0 防止bug。
类似python字典
对象由属性和方法组成,声明:
let obj = {
key:value,
属性名:属性值,
方法名:方法(函数)
}
使用——对象.属性名=new属性值
使用2——对象['属性名']
删除(不建议用,假删除):
delete 对象.属性
// for in遍历
for (let key in obj){
// 字符串形式的key
console.log(key)
}
var,let,const声明变量优先const
经常数学运算的简单数据类型
,如循环里的i用let声明
document(网页文档)/browser(浏览器) object model
DOM树节点:标签对象,所有属性方法基于最大的对象document
css选择器获取DOM:
document.querySelector('css选择器')
——只匹配第一个
获取到的;
document.querySelectorAll
选择所有对象,得到的是nodelist
(伪数组),可以遍历,有长度索引号,不可以push等操作
document.getElementById()
document.getElementsByTagName()
// 字符效果都生效
li.innerHTML = '更换标签内容
'
// 字符更改,效果不生效
li.innerText = '更换标签内容
'
herf,title(图片的提示语句),src等
const box =document.querySelector('.box')
box.style.width = '500px'
1、多熟悉style属性,小驼峰命名规则
行内样式,权限比较高,修改慎重
document.body.style.backgroundImage = `url(./images/desktop_${random}.jpg)`
2、类名className,直接用class与关键字冲突,className渲染时覆盖原来的class类名。
// 1. 获取元素
const div = document.querySelector('div')
// 2.添加类名 class 是个关键字 我们用 className
div.className = 'nav box'
3、classList
常用,结合js点击等事件更改类名实现效果更换
// 1、 获取
const box = document.querySelector('.box')
// 2、 修改
// 加
// box.classList.add('active')
// 删除
// box.classList.remove('active')
// 切换
box.classList.toggle('active')
ipt.checked = true
button.disabled = true // 禁用按钮
data-
开头的属性名
one.dataset
:可以得到一个对象
定时器是一个带有序号
的对象
// 开 setInterval(不带()的变量名,毫秒时间)
let n = setInterval(function(){
console.log('2miao')
},2000)
// 每个定时器有特定的序号
console.log(n )
// 关 clearInterval(变量名)
clearInterval(n)
语法:
元素对象.addEventListener('事件类型',执行函数)
1、鼠标事件
click,mouseenter,mouseleave
轮播图完整效果,养成开关切换前判断的好习惯:
// 自动轮播,借助向右click事件
let timeId = setInterval(function () {
next.click()
},1000)
// 鼠标事件
// 划入暂停
const slider = document.querySelector('.slider')
slider.addEventListener('mouseenter',function(){
clearInterval(timeId)
})
// 划走轮播重新开始
slider.addEventListener('mouseleave',function(){
if (timeId){
clearInterval(timeId)
}
timeId = setInterval(function () {
next.click()
},1000)
})
2、焦点事件
focus,blur
补充focus伪类选择器
input {
width: 200px;
}
input:focus {
width: 400px;
transition: all 0.4s;
}
3、键盘事件
Keydown
Keyup
4、文本事件
input
1、获取事件对象
元素对象.addEventListener('事件类型',function(e) { })
function 里命名的形式参数即事件对象,建议命名 event,ev,e
2、属性方法
if (e.key === 'Enter') {
// 如果用户输入的不为空就显示和打印
if (tx.value.trim()) {
// console.log(11)
item.style.display = 'block'
// console.log(tx.value) // 用户输入的内容
text.innerHTML = tx.value
}
// 等我们按下回车,结束,清空文本域
tx.value = ''
// 按下回车之后,就要把 字符统计 复原
total.innerHTML = '0/200字'
}
复选框案例复盘
1、大复选框的选中状态,如果获取大框时CSS选择器选择‘.allCheck’,ckAll.checked为undefined
2、小复选框要用querySelectorAll()方法拾取,再进行遍历
3、css属性要多了解多熟悉,比如.checked
4、多调试
this指向到调用者
事件完整执行过程中的传递流动路径
1、两个阶段
捕获与冒泡
2、事件捕获
3、事件冒泡与阻止
一个元素触发后,会依次向上调用所有父级元素的同名(类型)事件;
冒泡是默认触发的,所以有时候需要阻止
mouseenter,leave方法没有冒泡
mouseover,out方法有冒泡
4、解绑事件
捕捉的事件对象.removeEventListener()
5、阻止元素默认行为
e.preventDefault()
利用冒泡解决需求的技术技巧
1、页面加载事件:load,场景:window
HTML的document文档完全加载解析事件,无需等待样式表、图像2、等资源完全加载:DOMContentLoaded
3、页面滚动事件:scroll,场景:window或者元素
4、页面元素尺寸事件
resize,
clientWidth,clientHeight,元素宽和高,距离包含padding,不包含border边框
offsetWidth,offsetHeight,宽高距离包含padding边框,
offsetLeft,offsetTop受到父级的定位元素的影响
getBoundingClientRect,相对于视口的距离
1、实例化
const date = new Date()
const date = new Date(‘2023-08-01 12:00:00’)
2、时间对象方法
getMonth(),0-11,月份+1
getDate(),几号
getDay(),0-6,星期,周日是0
3、时间戳
1970/01/01 00:00:00
getTime();
+new Date();常用,可以指定时间。
Date.now();
元素节点
:标签
属性节点:class,id
文本节点
1、查找,都是属性,不需要加()调用方法:通过父子级关系查找对应元素,简化代码。parentNode,childNode获得子节点的所有属性,内容等,常用 父元素.children
- 1
- 2
- 3
- 4
- 5
2、增加
先创建,后增加
const li = document.createElement('li')
ul.insertBefore(li, ul.children[0])
可能用途:评论留言板,新章节更新等(循环生成 也可)
3、克隆,删除
元素.cloneNode(布尔值)
父元素.removeChild(元素名称)
touch:
touchstart
touchmove
touchend
js插件:swiper
1、定时器-延时函数,区别于间歇循环函数
setTimeout(回调函数,等待毫秒数)
2、js单线程,但是html5的web woker标准允许js类似python可以做到同步和异步(js通过回调函数实现。网络模块ajax,普通监听事件resize,click等,资源加载load,error等,定时器;加入任务队列)。
3、location
.href:跳转链接
.search:?get请求部分
.hash:#路由查询部分
.reload:刷新当前页面
4、navigator:userAgent等浏览器信息
5、history:后退前进的浏览历史栈
forward,back,go(1),go(-1)
存在浏览器中,容量较大,sessionStorage和localStorage约 5M 左右,存储类型是字符串
,关闭浏览器不会消失
localStorage.setItem(key,value)
浏览器-检查-application-localstorage
普通对象转换为json字符串,然后再转换成json字符串对象:
JSON.stringify(obj)、JSON.parse(str)来回转换方法
// 1.复杂数据类型存储必须转换为 JSON字符串存储
localStorage.setItem('obj', JSON.stringify(obj))
// JSON 对象 属性和值有引号,而是引号统一是双引号
// {"uname":"pink老师","age":18,"gender":"女"}
// 取
// console.log(typeof localStorage.getItem('obj'))
// 2. 把JSON字符串转换为 对象
const str = localStorage.getItem('obj') // {"uname":"pink老师","age":18,"gender":"女"}
console.log(JSON.parse(str))
sessionStorage:关闭浏览器会消失
map:映射对象里的每个元素并返回一个新数组
join:所有元素转换成一个字符串
map+join一起用来渲染数据
Regular Expression
1、语法://
// 返回布尔值
console.log(reg.test(str));
// 返回数组
console.log(reg.exec(str));
2、元字符
[a-z][A-Z][0-9]等严格要求的特殊字符。
量词 | 说明 |
---|---|
* | 重复0次或者多次,不存在也可 |
+ | 重复1次或者多次,至少出现1次 |
? | 重复0次或者1次 |
{m} | 限定重复m次 |
{m,} | 重复m次或者多次,至少重复m次 |
{m,n} | 限定重复m到n次,包括m,n |
任何 一个
字符即可 if (reg.test(this.value)) {
span.innerHTML = '输入正确'
span.className = 'right'
} else {
span.innerHTML = '请输入6~16位的英文数字下划线'
span.className = 'error'
}
3、修饰符
常见模式的简写方式
预定义类 | 说明 |
---|---|
\d | [0-9],0-9里任一数字 |
\D | [ ^0-9],上面的取反 |
\w | [a-zA-Z0-9_],任一数字字母和下划线 |
\W | [^a-zA-Z0-9_],上面的取反 |
\s | [\t\r\n\v\f],换行符,制表符,空格符 |
\S | 上面的取反 |
举例,日期格式:
^\d{4}-\d{1,2}-\d{1,2}
|:或,前端的或是||,正则里面是一个|
4、修饰符,写在语句末尾/的后面
i:不区分大小写
g:global,全局搜索
replace:替换。replace(//,‘被替换的内容’)
1、函数作用域
2、块作用域
{ }
包裹的作用域里的变量是局部变量,外部不可以访问,执行完毕之后垃圾回收,let,const声明产生块作用域,var不产生,所以不建议用var声明变量。函数(立即执行函数)、if、for等也可以认为块作用域
{ }外层,即标签或者单独的js文件里的可全局访问变量
变量的底层查找机制,类似编辑器配置解释器、环境变量的顺序。
内存的分配-使用-回收
1、内存泄漏-内存分配后未被回收或者无法释放
2、堆栈空间分配区别:
浏览器-断点-souce-closure
概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域
简单理解:闭包 = 内层函数+外层函数的变量
通过闭包可以让外部访问函数内部变量,实现数据私有化,但是可能引发数据泄漏
unction outer() {
let a = 10
function inner() {
console.log(a);
}
return inner
}
const fn = outer()
fn()
var声明
的变量会提升到当前作用域的最前,只提升声明定义,不提升赋值,不建议用var。let,const不存在此问题。
同变量提升类似。代码解析时候, 函数声明提升到当前作用域的最前面。建议先声明后调用,尤其是函数表达定义的函数var fn = function(){}
必须先声明
类似于python函数参数
1、动态参数,arguments
,伪数组
2、剩余参数,...arr
,真数组,建议用剩余参数
区别数组的展开运算符 ...
。使用场景:求最大值;合并数组
const arrsy = [1,2,3]
console.log(...arrsy);
const arr1 = [2,2,2]
console.log([...arr1,...arrsy]);
简短代码。不绑定特定this,替代匿名函数的地方
const fn = function () {
console.log('fn:', 123);
}
fn()
// 1 箭头函数基本语法
const fn1 = () => {
console.log('fn1 基本语法:', 123);
}
fn1()
// 2 带参数
const fn2 = (x) => {
console.log('fn2 带参数 :', x);
}
fn2(1)
// 2.1 只带1个参数可省略小括号,无参数或者多参数都必须有小括号占位
const fn201 = x => {
console.log('fn2.1 一个参数省略小括号,无参数或者多参数都必须有小括号占位:', x);
}
fn201(2.1)
// 2.2 多个参数可以用剩余参数...args
const fn202 = (...arr) => {
let nsum = 0
for (let i = 0; i < arr.length; i++) {
// console.log(arr[i]);
nsum = nsum + arr[i]
}
return nsum
// console.log(nsum);
}
let res = fn202(1, 2, 3)
// console.log(res);
console.log('2.2 多个参数可以用剩余参数...args', res);
// 3 只带1行可以省略大括号
const fn3 = x => console.log('fn3 一行逻辑代码省略大括号:', x);
fn3(3)
// 3.1 只带1行的return可以省略大括号和return
// const fn301 = x => {
// return x+x
// } ;
const fn301 = x => x + x;
console.log('3.1 只带1行的return可以省略大括号和return', fn301(3))
// 4、直接返回一个对象,避免大括号冲突,对象外侧用小括号包裹
// const fn4 = (uname) => ({ name:uname})
const fn4 = (uname) => ({ uname: uname })
console.log('fn4 返回对象,避免大括号冲突,对象外侧用小括号包裹', fn4("刘德华"))
没有动态参数,但是有剩余参数
this指向:
// 普通函数
console.log(this); // => window
function fn6() {
console.log(this); // =>fn => window
}
fn6()
// 普通函数
const obj = {
name : 'andy',
sayHi :function(){
console.log(this); // => sayHi => obj
}
}
obj.sayHi()
// 箭头函数,没有自我绑定的this,用的this指向上层作用域的this
const fn7 = () => console.log(this); // => 上层fn7的this =>window
fn7()
const obj2 = {
name : 'andy',
sayHi :() => {
console.log(this); // => sayHi没有this,上层obj2的this =>window
}
}
obj2.sayHi()
箭头函数this容易乱,不建议用在DOM回调函数中
解构赋值是一种快速为变量赋值
的简洁语法,本质上仍然是为变量赋值。
数组解构是将数组的单元值
快速批量赋值给一系列变量
的简洁语法。
应用:快速交换[a,b] = [b,a]
,注意:前面必须加;
。立即执行函数也要加;
对象解构是将对象属性和方法
快速批量赋值给一系列变量
的简洁语法
forEach()
方法用于调用数组的每个元素,并将元素传递给回调函数
filter()
方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
主要使用场景: 筛选数组符合条件的元素,并返回筛选之后元素的新数组
创建对象3种方式:
1、字面量直接创建
2、利用 new Object 创建
3、构造函数,即封装函数
实例成员:
通过构造函数创建的对象称为实例对象,实例对象
中的属性和方法称为实例成员。
静态成员:
构造函数
的属性和方法被称为静态成员
Object,Date,Math,Array,String,Number等
1、Object常用方法:
keys
,vlaues
,assign合并多个对象到目标对象并返回目标对象
2、Array
join(数组-字符串)
,find
,every
,some,concat
,sort,splice
,reverse,findIndex
,map
,reduce(fun(),0)
,filter
,fill,forEach
伪数组转换成标准数组:form()
3、String
split(字符串-数组),substring(),replace,startsWith,endsWith,includes
toUpperCase,toLowerCase,slice,indexOf
可以使用length
计算长度
4、Number
number()转换数字
toFixed()保留小数位数
小数一般保留2位,计算小数时由于精度问题,建议先×100变整数后计算结果再除以100
面向过程和面向对象。面向过程是基础,面向对象是技术成熟的流水线。
浪费内存
问题解决原来的构造函数内存
使用问题
1、原型对象 prototype
构造函数
有属性prototype指向一个对象
,即原型对象 ,
公共的属性可以定义到构造函数里
公共的方法写到原型对象上
原型对象(方法)的this指向实例对象
原型对象prototype的constructor(构造函数)属性 ,指回所属的构造函数
const ldh = new Star('刘德华', 55)
const zxy = new Star('刘德华', 55)
// 即便参数一样,new出来的对象不同
console.log(ldh === zxy) // false
2、对象原型 proto
实例对象中有对象原型__proto__指向原型对象
prorotype
实例对象.proto === f.prototype
凡是对象都有__proto__
按自己的理解加了定语的__proto__区别prorotype代码示例以便参考:
function Star() { }
const ldh = new Star()
console.log(ldh.__proto__);
// 实例的__proto__(对象原型:实例对象的原型)指向该构造函数的prototype(原型)
console.log(ldh.__proto__ === Star.prototype); // true
// 实例的__proto__(对象原型)里有constructor指向该构造函数
console.log(ldh.__proto__.constructor == Star); // true
共有的属性和方法有那些,然后做个构造函数,进行封装,一般公共属性写到构造函数内部,公共方法,挂载到构造函数原型身上。
子类 = new 父类()
类比作用域链。原型链是__proto__的指向链,是一种查找方法。
可以用instanceof方法查找原型链上是否含有方法
浅拷贝只拷贝对象的第一层,内层嵌套还是引用
赋值用的深拷贝,拷贝引用
1、函数递归
函数内部调自己,需要有return终止条件
for in 对象遍历数组均可
map foreach 数组遍历
2、lodash/cloneDeep
npm的js库
3、JSON.stringify()——parse()
把对象转换成json字符串,再复制就没有复杂数据类型问题。
1、throw
自动中断程序,Error常见错误类型
2、try/catch finally
try/catch不自动中断程序,如果在try中遇到错误,可以catch中结合throw一下。
finally处理一些代码收尾工作
function fn() {
try {
// 可能发送错误的代码 要写到 try
const p = document.querySelector('.p')
p.style.color = 'red'
} catch (err) {
// 拦截错误,提示浏览器提供的错误信息,但是不中断程序的执行
console.log(err.message)
throw new Error('你看看,选择器错误了吧')
// 需要加return 中断程序
// return
}
finally {
// 不管你程序对不对,一定会执行的代码
alert('弹出对话框')
}
console.log(11)
}
fn()
3、debugger
断点调试
1、指向
普通函数指向调用者
箭头函数本身没有this,绑定最近一级外层的this 。
构造函数,原型对象里不建议用this
2、改变指向
1、call(thisarg(改变this指向,不占用形参位置),arg1,arg2,)
调用函数,顺带参数值
2、apply(thisarg,[argsArray])
可以求数组中的最大值,之前用:
1、遍历比较
2、展开运算符计算Math.max(…arr)
Math.max.applay(Math,arr)
3、bind(thisarg,arg1,arg2,)
返回(赋值)一个改变this指向的新函数(包括传递的参数),需要接受,后续可以调用新函数。
1、防抖 debounce:短时间频繁触发,最后一次有效,验证表单,鼠标滑动,轮播图防抖等
2、节流 throttle:短时间频繁触发,第一次有效,高频鼠标抖动滑轮滑动应用等。防抖节流的区别在于
1>fn()调用和定时器清空的前后问题,
2>定时器的清除方式timer = null
lodash节流防抖:
// box.addEventListener('mousemove', mouseMove)
// lodash 节流写法
// box.addEventListener('mousemove', _.throttle(mouseMove, 500))
// lodash 防抖的写法
box.addEventListener('mousemove', _.debounce(mouseMove, 500))
1、发现前面html中的表格基础操作已经忘的差不多了
2、css中的几个text-align,center和沿轴对齐方式的属性比较混淆也需要复习一下,查找了几个帖子,但感觉还不是很清晰的做出区别
轮播图案例中的
img的src和url属性在css中使用场景的区别:
1、src(img、script、iframe):浏览器解析html时会先加载scr中的资源,此时会阻塞HTML页面的加载,而href则不会,这也是引用的js文件要放在标签后面的原因,否则如果放在head中js代码要放在window.onload中,而引用的css文件直接可以放在head中,它是通过link加载的不会阻塞页面。
2、URL(Uniform Resource Locators)是资源定位规则,而src、href是标签的属性,而且scr可以利用url进行页面请求
3、href(a,link)用于在当前文档和引用资源之间确立关系
参考链接: 分析href、src、url的区别
id部分有缺陷,在后面视频讲解的本地化完整版案例中已经修正
// id部分有缺陷,删除后新添id会重复,新添全局变量以作修正,纯属语法练习参考。其实直接定个自增变量,每次点击submit出发学号+1也就可以了
// stuId: arr.length + 1,
stuId: maxId = maxId>=arr.length + 1?maxId+1:arr.length + 1,
节流阀:定义变量=true,if条件转换flase
值变化change事件:正则的内容结果发生变化触发
// 使用change事件 值发生变化的时候
username.addEventListener('change', verifyName)
// 使用兄弟元素来定位
const span = username.nextElementSibling
鼠标放大图片案例
事件委托里,e和this的区别
1、e.target返回的是触发事件的对象(元素)
2、this返回的是绑定事件的对象(元素)
两者作用在没有父子级嵌套的对象上没有区别的,但是如ul>li嵌套结构,如下代码:
- 123
- 123
- 123
// script
var ul = document.querySelector('ul');
ul.addEventListener('click', function (e) {
// 事件委托的结果是li,事件委托一般要注意父级冒泡和兄弟元素间伴随的css效果change
console.log(e.target);
// 结果是ul,绑定对象是什么就是什么
console.log(this);
})
vscode快捷键:
1、ctrl(command)+d多选相同的字母变量
2、option+shift+上下方向键快速复制
ontimeupdate(),每秒多次。触发很快,节流可以实现触发少数几次,然后根据触发次数确定视频播放节点。lodash模块有封装方法。
onloadeddata(),加载点 currentTime设置好