Starting again-03
css
1.css选择器的优先级
!important > 行内样式 > id > 类 > 标签 > 全局选择样式
2.隐藏元素的方法
display:none 元素在页面消失并且不占用空间;
opacity:0 透明度为0占用空间;
visibility:hidden 元素消失,占据空间,一种不可见的状态;
3.px与rem
px:像素,绝对单位;
rem:相对单位,相对于根节点的font-size值;
根节点设置为font-size:62.5% 1rem=10px 计算公式:16px*62.5%=10px;
4.重绘与重排(回流)
重排(回流):根据样式设定盒子在页面上的位置与大小,对于Dom的大小位置修改;
重绘:重排完成后,浏览器根据盒模型的特性进行绘制,对于样式设定;
浏览器的渲染机制:
5.css属性继承
css的三大特性:继承,层叠,优先级
字体属性:font,文字属性:line-height,元素可见性:visibility:hidden,表格布局:border-spacing,列表属性:line-style;
6.css预处理器
预处理 添加变量,函数,混入等功能,Sass,Less; 样式的嵌套,属性变量设定。
js
1.js的三部分组成
ECMAScript: js的和兴内容,语言的基础语法,如var for 数据类型(字符串,数组)
文档对象模型(DOM):DOM元素构建html页面
浏览器对象模型():对浏览器窗口进行访问和操作
2.js常用的内置对象
object:对应的一些通用属性与方法toString(),valueOf()转换为原始值。
Array:数组的相关操作,push() pop()添加与删除末尾元素,map() filter()映射与过滤,slice() splice()截取与修改
String:字符串相关操作indexOf() includes()查找子串,split() join()分割与拼接,substring() slice()截取子串
Math:数学相关的方法与属性,Math.random(),Math.max() Math.min()
Date:日期与时间,获取当前时间new Date(),格式化:getFullYear(),getMonth(),时间戳getTime()(返回毫秒数)
Json:JSON.stringify()
:将对象转为 JSON 字符串,JSON.parse()
:将 JSON 字符串解析为对象
等等
3.数组的常用方法
添加 / 删除元素:
push()
:向末尾添加元素,
pop()
:删除末尾元素,
unshift()
:向开头添加元素,
shift()
:删除开头元素,
splice(start, deleteCount, ...items)
:删除 / 插入元素;
数组转换与筛选:
map(callback)
:返回新数组(每个元素经回调处理)
filter(callback)
:返回新数组(满足条件的元素)
slice(start, end)
:返回截取的新数组
concat(...arrays)
:返回合并后的新数组
flat(depth)
:返回扁平化后的新数组
查找与判断:
find(callback)
:返回第一个满足条件的元素
findIndex(callback)
:返回第一个满足条件的元素索引
indexOf(value)
:返回值的索引(无则 -1
)
lastIndexOf(value)
:从末尾开始查找索引
includes(value)
:判断是否包含值(返回布尔值)
every(callback)
:判断所有元素是否满足条件
some(callback)
:判断是否有元素满足条件
4.对数据类型的检测
检测场景 | 推荐方法 |
---|---|
基本类型(除 null) | typeof |
null | value === null |
数组 | Array.isArray() 或 getType() |
几乎所有类型(包括基本类型和引用类型) | Object.prototype.toString.call() |
检测引用类型(如数组、日期、自定义对象等) | instanceof |
5.内存泄漏的理解
内存泄漏的本质就是垃圾回收机制失效。
js内存泄漏的场景
意外的全局变量:未声明的变量自动变为全局变量
function test() {// 未使用let/const声明,成为全局变量leakVar = "这会一直存在直到页面关闭";
}
定时器与事件监听未清除
// 忘记清除的定时器
setInterval(() => {console.log("这个定时器会一直运行");
}, 1000);
闭包持有外部变量引用
function outer() {const largeData = new Array(1000000).fill('data');return function inner() {// 即使不使用largeData,闭包也可能导致其无法回收console.log('inner function');}
}
const keepRef = outer(); // 持有inner引用,间接导致largeData无法释放
6.事件委托(冒泡机制,绑定事件在父元素上)项目管理系统中门户跳转
事件委托利用了事件冒泡的特性:当子元素触发事件时,事件会逐级向上传播到父元素。因此,将事件监听器绑定到父元素上,而不是每个子元素,从而统一处理所有子元素的事件。
阻止冒泡e.stopPropagation(),项目管理系统中点击父元素是跳转,子元素是弹窗
<template><ul @click="handleItemClick"><li v-for="(item, index) in list" :key="item.id":data-id="item.id" <!-- 绑定数据ID -->>{{ item.name }}</li></ul>
</template><script>
export default {data() {return {list: [{ id: 1, name: '项目1' },{ id: 2, name: '项目2' },{ id: 3, name: '项目3' }]};},methods: {handleItemClick(e) {// 查找最近的li元素(处理子元素点击情况)const li = e.target.closest('li');if (li) {const itemId = parseInt(li.dataset.id);const item = this.list.find(item => item.id === itemId);console.log('点击了项目:', item);}}}
};
</script>
7.prototype
和 __proto__
有什么区别?如何理解它们的关系?
原型链:实例对象在调用属性和方法的时候,依次从实例本身,构造函数原型,原型的原型上查找。
__proto__
是实例对象的原型指向,prototype
是构造函数的属性;
构造函数的 prototype
是其实例的 __proto__
。
function Foo() {}
const f = new Foo();
// 请解释以下输出
console.log(f.__proto__ === Foo.prototype);
console.log(Foo.__proto__ === Function.prototype);
console.log(Foo.prototype.__proto__ === Object.prototype);
8.new操作符执行工作原理
- 创建一个空对象
- 将空对象的原型指向构造函数的prototype
- 执行构造函数,将this绑定到新对象
- 构造函数返回了对象,则返回该对象,否则返回新创建的对象
// 3. 模拟new操作符的自定义函数
function myNew(constructor, ...args) {// 步骤1:创建一个空对象const obj = {};// 步骤2:将空对象的原型指向构造函数的prototypeobj.__proto__ = constructor.prototype;// 步骤3:执行构造函数,将this绑定到新对象const result = constructor.apply(obj, args);// 步骤4:如果构造函数返回了对象,则返回该对象,否则返回新创建的对象return typeof result === 'object' && result !== null ? result : obj;
}
9.script标签中async(异步不保证顺序)与defer(保证顺序)
特性 | 无属性(默认) | defer | async |
---|---|---|---|
下载时是否阻塞 HTML 解析 | 是 | 否 | 否 |
执行时是否阻塞 HTML 解析 | 是 | 否(等待 HTML 解析完成后执行) | 是(下载完成后立即执行) |
执行顺序 | 按出现顺序 | 按出现顺序 | 不保证顺序(取决于下载速度) |
与 DOM 的关系 | 可能需要等待前面的 DOM | 确保在 DOM 解析完成后执行 | 不确定(可能在 DOM 就绪前执行) |
选择建议 | 脚本必须在特定位置立即执行(如修改当前 HTML 内容),或脚本执行依赖于其前面的 HTML 结构 | 脚本之间有依赖关系,或依赖 DOM 结构,需要按顺序执行 | 脚本独立且不依赖 DOM,也不依赖其他脚本(如统计分析脚本) |
10.前端定时器setTimeout(执行一次),setInterval(重复执行)
对比维度 | setTimeout | setInterval |
---|---|---|
执行逻辑 | 延迟指定时间后,只执行 1 次回调函数 | 每隔指定时间,重复执行回调函数,直到被清除 |
最小理论时间 | 约 1ms(部分浏览器早期限制为 4ms,现已普遍支持 1ms) | 同setTimeout ,约 1ms |
核心用途 | 单次延迟任务(如 3 秒后弹出提示、页面加载完成后延迟执行动画) | 周期性任务(如每秒更新倒计时、实时刷新数据图表、轮播图自动切换) |
清除方式 | 需调用clearTimeout(定时器ID) 手动清除 | 需调用clearInterval(定时器ID) 手动清除,否则会一直执行 |
11. call(参数列表) apply(数组) bind()返回函数 改变this指向
call:传参数列表(立即执行)
apply:传递数组(立即执行)
bind:传参后返回一个改变后的this指向函数(不会立即执行)
// 定义一个对象
const person = {name: "张三",age: 30,sayHello: function(greeting, punctuation) {console.log(`${greeting}, 我叫${this.name}${punctuation}`);}
};// 另一个对象
const anotherPerson = {name: "李四"
};// 使用 call() 改变 this 指向
person.sayHello.call(anotherPerson, "你好", "!"); // 输出:你好, 我叫李四!// 使用 apply() 改变 this 指向
person.sayHello.apply(anotherPerson, ["哈喽", "~"]); // 输出:哈喽, 我叫李四~// 使用 bind() 改变 this 指向
const newFunc = person.sayHello.bind(anotherPerson, "Hi");
newFunc("!"); // 输出:Hi, 我叫李四!
12.递归函数(渲染多级嵌套表单)
递归函数:一个函数调用函数本身(函数内部调用自己)
递归函数必须要有退出条件return
// 嵌套菜单数据
const menu = [{id: 1,name: "首页",children: []},{id: 2,name: "产品",children: [{ id: 21, name: "产品A", children: [] },{ id: 22, name: "产品B", children: [{ id: 221, name: "产品B-1" }] }]}
];// 递归渲染菜单
function renderMenu(items) {return items.map(item => (<li key={item.id}><span>{item.name}</span>{item.children.length > 0 && <ul>{renderMenu(item.children)}</ul>}</li>));
}// 使用:<ul>{renderMenu(menu)}</ul>
13.事件循环->同步任务->微任务->宏任务
循环机制如下
1.同步任务直接执行
2.遇到微任务放进微任务队列(promise.then,process.nextTick,async/await等等)
3.遇到宏任务放进宏任务队列(定时器,网络请求)
4.执行完所有同步任务
5.执行微任务队列中的任务
6.执行宏任务队列中的任务
执行顺序1 5 3 4 2
console.log('1'); // 同步任务setTimeout(() => {console.log('2'); // 宏任务
}, 0);Promise.resolve().then(() => {console.log('3'); // 微任务
}).then(() => {console.log('4'); // 微任务
});console.log('5'); // 同步任务
14.get(url 大小限制 浏览器缓存)-查询与post(请求体中 无限制 不缓存)-提交
get:通过 URL 传递参数(?key=value
形式),参数明文在URl中,大小受限(2k-8k),会被浏览器缓存,记录在浏览器历史中。get应用场景:查询数据(搜索,分页,获取详情)
post:数据存放在请求体(request body)中,数据不显示url中,大小理论不限制(服务器配置),默认不缓存,不被浏览器记录。post应用场景:提交数据(表单,上传文件,创建修改资源)
15.promise与async await区别
1.处理异步请求的方式
2.promise es6引入三种状态(pending fulfilled rejected) ,async await es7提出基于前一种的语法糖,都是非阻塞性的。
3.promise.then,使用catch去处理和捕获异常,书写方式链式
async await通过 try catch捕获异常,遇到await会返回结果,再执行后面操作。promise.then()方式返回会出现请求还没返回就执行了后面的操作
promise
fetchData1().then(data1 => {console.log(data1);return fetchData2(data1.id);}).then(data2 => {console.log(data2);return fetchData3(data2.id);}).then(data3 => {console.log(data3);}).catch(error => {console.log(error);});
async await
async function handleData() {try {const data1 = await fetchData1();console.log(data1);const data2 = await fetchData2(data1.id);console.log(data2);const data3 = await fetchData3(data2.id);console.log(data3);} catch (error) {console.log(error);}
}handleData();