注意事项(基础)
1.js的基础数据类型:
基本数据类型:undefined,null,number,string,boolean
引用类型(都算作对象Object):Object,Array,Function
ES6新增了一种Symbol,这种类型的对象用不相等,即使创建的时候传入相同的值,可以解决属性名冲突的问题,作为标记
2.浏览器的内核
- IE浏览器内核:Trident内核(Trident:三叉戟),俗称IE内核
- Chrome浏览器内核:统称Chromium或chrome内核,以前是Webkit内核,现在是Blink内核
- Firefox浏览器内核:Gecko(gecko:壁虎)内核,俗称Firefox内核
- Safari浏览器内核:Webkit内核
- Opera浏览器:最初是自己的Presto内核,后来是Webkit,现在是Blink内核
浏览器的内核分两部分:渲染引擎和JS引擎。
webkit内核是苹果公司的,blink内核是webkit的分支内核
3.BOM对象有哪些?
1.window对象:是JS最顶层对象,其他的BOM对象都是Window对象的属性
2.document对象:文档对象
3.location对象:浏览器当前的url信息
4.navigator对象:浏览器本身信息
5.screen对象:客户端屏幕信息
6.history对象:浏览器访问历史信息
4.em和rem的区别,
em相对于父元素,rem相对于根元素
5.在使用foreach遍历数组的话,使用break不能中断循环,使用return也不能返回到外层函数
6.for in 和 for of的区别,
for in遍历的是数组的索引(即键名),而for of遍历的是数组的元素值
for of 遍历的是数组内的元素,不包括数组的原型属性method和索引name
for (var index in arr){
}
for in遍历数组的缺点:
1.index索引为字符串型数字,不能直接进行几何运算
2.遍历顺序有可能不是按照实际数组的内部顺序
3.使用for in会遍历数组所有的可枚举属性,包括原型。例如以下遍历数组的原型方法method和name属性
var arr = [1,2,3,4,5,6,7,8,9];
arr.name = "数组";
Array.prototype.method = function(){
console.log(this.length);
}
for (var index in arr){
console.log(arr[index]);
}
4.for in适合遍历一个对象,for of遍历对象时会报错
var obj = {name:'安妮',age:100,sex:'女'};
Object.prototype.sayHello = function(){
console.log('Hello');
};
Object.prototype.str = '原型中的属性';
for(let index in obj){
console.log(index);
}
5.只要数据结构部署了Symbol.iteratoer属性,就可以使用for of循环
- 数组
- Map
- Set
- String
- arguments对象
- Nodelist对象,就是获取的dom列表集合
凡是部署了iterator接口的数据结构,也都可以使用扩展运算符和解构赋值等操作
- call,apply ,bind
call ,apply,bind都是改变this指向的方法,
call
fn.call(thisArg,arg1,arg2,…)
thisArg:在fn函数运行时指定的this值,需要注意的是,指定的this值并不一定是该函数执行时
真正的this值,
非严格模式:不传参数,或者第一个参数是null或undefined,this都指向window。
严格模式,第一个参数是谁,this就指向谁,包括null和undefined,如果不传参数this就是undefined
apply
fn.apply(thisArg,[argsArray]),和call用法一样,第二个参数传递的是一个数组或者类数组对象
bind
bind语法和call一模一样,区别在于立即执行还是等待执行,bind不兼容IE 6,7 8
fn.call(obj,1,2); //改变fn中的this,并且把fn立即执行
fn.bind(obj,1,2); //改变fn中的this,fn并不执行
this改变为obj了,但是绑定的时候立即执行,当触发点击事件的时候执行的是fn的返回值undefined
document.onclick = fn.call(obj,1,2);
bind 会把fn中的this预处理为obj,此时fn没有执行,当点击的时候才会把fn执行
document.onclick = fn.bind(obj,1,2);
8.cookie sessionStorage localStorage区别
考察点:本地存储
cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递
cookie数据还有路径(path)的概念,可以限制,cookie只属于某个路径下
存储大小限制也不同,cookie数据不超过4K,同时因为每次http都会携带cookie,所以cookie只适合保存很小的数据,如会话标识
webStorage虽然也有存储大小的限制,但是比cookie大得多,可以达到5M或更大
数据的有效期不同:sessionStorage,仅在当前的浏览器窗口关闭有效,localStorage始终有效,
窗口或浏览器关闭也一直保存,因此用作持久数据,cookie,只在设置的cookie过期时间之前一直有效
,即使窗口和浏览器关闭,
作用域不同: sessionStorage:不在不同的浏览器窗口中共享,即使同一个页面;localStorage:在所有的同源窗口都是共享的,cookie:也是在所有的同源窗口中共享的
9.适配移动端
- 流式布局:百分比布局实现在移动端的宽高自适应
- 响应式布局:CSS3媒体查询
- REM(弹性)布局:实现盒子的宽高自适应
最标准的viewport设置:
视口宽度和设备保持一致
视口的默认缩放比例1.0
不允许用户自行缩放
最大允许的缩放比例1.0
最小允许的缩放比例1.0
流式布局:在css2时代就有,主要靠百分比进行排版,网页中主要的划分区域的尺寸使用百分数(搭配min,和max使用)
缺点:宽度使用百分比定义,但是高度和文字大小大多都是用px来固定,所以在大屏幕手机下显示效果会变成有些页面元素宽度被拉的很长,但是高度,文字大小还是和原来一样
响应式布局:响应式布局的关键技术是CSS3中的媒体查询,监测设备屏幕大小,通过媒体查询有针对性的更改页面的布局
布局特点:每个屏幕的分辨率下面会有一个布局样式,即元素位置和大小都会变
优点:适应pc和移动端,如果足够耐心,效果完美
缺点:媒体查询是有限的,也可以枚举出来,只能适应主流的宽高。工作量大,设计需要多个版本
REM布局
rem的定义:rem相对于根元素设置字体大小,这就意味着,我们只需要根据自己的需求在根元素确定一个参考值
rem 与 em, px 的区别:
px:像素,比较精确的单位,但是不好做响应式布局
em:以父节点font-size大小为参考点,标准不统一,容易造成混乱
@media screen and (min-width: 640px) {
html {
font-size: 100px;
}
}
@media screen and (max-width: 639px) and (min-width: 480px){
html {
font-size: 75px;
}
}
@media screen and (max-width: 479px) and (min-width: 414px){
html {
font-size: 64.6875px;
}
}
@media screen and (max-width: 413px) and (min-width: 375px){
html {
font-size: 58.59px;
}
}
@media screen and (max-width: 374px) and (min-width: 360px){
html {
font-size: 56.25px;
}
}
@media screen and (max-width: 359px){
html {
font-size: 50px;
}
}
10.数组去重
- set方法去重
let arr = [1,0,0,2,9,8,3,1];
function unique(arr) {
return Array.from(new Set(arr))
}
console.log(unique(arr)); - 双重for循环在利用数组splice方法去重(ES5常用)
var arr = [1, 5, 6, 0, 7, 3, 0, 5, 9,5,5];
function unique(arr) {
for (var i = 0, len = arr.length; i < len; i++) {
for (var j = i + 1, len = arr.length; j < len; j++) {
if (arr[i] === arr[j]) {
arr.splice(j, 1);
j–; // 每删除一个数j的值就减1
len–; // j值减小时len也要相应减1(减少循环次数,节省性能)
// console.log(j,len)
}
}
}
return arr;
}
console.log(unique(arr)); - 利用indexOf
var arr =[1,-5,-4,0,-4,7,7,3];
function unique(arr){
var arr1 = []; // 新建一个数组来存放arr中的值
for(var i=0,len=arr.length;i<len;i++){
if(arr1.indexOf(arr[i]) === -1){
arr1.push(arr[i]);
}
}
return arr1;
}
console.log(unique(arr)); // 1, -5, -4, 0, 7, 3
4.使用数组sort()方法(相邻元素对比法)
var arr = [5,7,1,8,6,9,6,0,4,2,3,2,6,2,2];
function Sort(arr){
let newArr = arr.sort((a,b)=>a-b);
let arr1 = [];
console.log(newArr);
for(let i=1;i<newArr.length;i++){
if(newArr[i-1] !== newArr[i]){
arr1.push(newArr[i]);
}
}
return arr1;
}
console.log(Sort(arr));
5.使用filter
var arr = [5,7,1,8,6,9,6,0,4,2,3,2,6,2,2];
function arrfilter(arr){
return arr.filter((item,index)=>{
return arr.indexOf(item) == index;
})
}
console.log(arrfilter(arr));
6.使用includes()方法 (includes方法用来判断一个数组是否包含一个指定的值,如果是返回true,否则返回false)
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
[1, 2, NaN].includes(NaN); // true
var arr = [5,7,1,8,6,9,6,0,4,2,3,2,6,2,2];
function arrIncludes(arr){
let newArr = [];
for(let i=0;i<arr.length;i++){
if(!newArr.includes(arr[i])){
newArr.push(arr[i]);
}
}
return newArr;
}
console.log(arrIncludes(arr));
11.ES6新增
const(声明常量), let(声明变量)关键字;
map 和 set 数据类型;
模板字符串
; 对象数组解构赋值;
函数剩余参数;(…arg)
延展运算符;(…)
函数默认参数;fn(name=’zs’)
对象字面量的增强(属性名和属性值相同, 可缺省);
Promise 异步对象;
class 类的支持
1.当我们要对多个对象操作合并两个或者多个object的时候,我们可以使用Object.assign( );
Object.assign(target, ...sources)
var obj = {};
var obj1 = { a: 1, b: 2 };
var obj2 = { c: 3, d: 4 };
var obj3 = { e: 5, f: 6 };
// for(let k in obj2){
// obj1[k] = obj2[k];
// }
// for(let k in obj3){
// obj1[k] = obj3[k];
// }
// console.log(obj1);
Object.assign(obj,obj1,obj2,obj3);
console.log(obj);
2.解构赋值
3.模板字符串
4.字符串新增方法
String.repeat()方法返回一个新字符串,表示原字符串重复n次
var str = 'char';
var repeat = str.repeat(5);
console.log(repeat);
5.扩展运算符
ES5数组方法:
- forEach( );
- map()
- filter
- find
- every
- some
- reduce
6.reduce方法
array.reduce(function(total,currentValue,currentIndex,arr),initialValue)
1.代替map做一些简单的运算
var a = [10,20,30];
var res = a.reduce(function(sum,item,index){
console.log(sum);
console.log('index',index);
return sum + item;
},1);
console.log(res);
2.将一个对象数组中的某些属性的值抽出来,组成一个新的数组
var colors = [
{color:'pink'},
{color:'red'},
{color:'gray'}
]
var Arr = colors.reduce(function(colorArr,item,index){
colorArr.push(item.color);
return colorArr;
},[])
console.log(Arr);
React面试题:
高阶组件:高阶组件接收React组件作为参数,并且返回一个新的React组件,高阶组件本身是一个函数,并不是一个组件
7.Promise.race() 和 Promise.all()
Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例
const p = Promise.all([p1, p2, p3]);
p的状态由p1、p2、p3决定,分成两种情况
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数
Promise.race方法同样是将多个Promise实例,包装成一个新的Promise实例
const p = Promise.race([p1, p2, p3]);
只要p1,p2, p3之中有一个实例率先改变状态,p的状态就跟着改变,那个率先改变的Promise实例的返回值,就传递给p的回调函数
promise.race 不是只执行一个promise,而是只返回最快的promise的结果。
12.防抖或是节流
限制函数的执行次数
1.防抖:通过setTimeout的方式,在一定的时间间隔内,将多次触发变成一次触发
2.节流; 减少一段时间的触发频率
// 防抖是通过setTimeout的方式,在一段时间间隔内,将多次触发转为一次触发
var btn = document.getElementById('btn');
// btn.addEventListener('click',submit);
btn.addEventListener('click', debounce(submit, 1000));
function submit() {
console.log('submit');
}
function debounce(fn, timout) {
var t = null;
return function () {
if (t) {
clearInterval(t);
}
t = setTimeout(() => {
fn();
}, timout)
}
}
//节流是减少一段时间内的触发频率
var btn = document.getElementById('btn');
btn.addEventListener('click',throttle(submit,2000))
function submit(){
console.log('submit');
}
function throttle(fn,timout){
var begin = 0;
return function(){
var cur = new Date().getTime();
if(cur -begin > timout){
fn();
begin = cur;
}
}
}
13.闭包
1.javascript语言特殊之处,函数内部可以直接读取全局变量1.
var n=999;
function f1(){
alert(n);
}
f1(); // 999
2.函数外部无法读取函数内的局部变量
function f1(){
var n=999;
}
alert(n); // error
3.函数内部声明变量的时候,一定要使用var命令,如果不用的话,你实际上就声明了一个全局变量
function f1(){
n=999;
}
f1();
alert(n); // 999
函数f2就被包含在函数f1内部,这时f1内部所有局部变量,对f2都是可见的,但是反过来不行
f2内部的局部变量,对f1是不可见的,这就是js语言的特点,被称为”链式作用域结构”。子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
function f1(){
var n=999;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
既既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗! f2还函数,就是闭包
闭包:就是能够读取其他函数内部变量的函数
只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解为,定义在函数内部的函数
闭包的用途
闭包最大用处有两个:1.可以读取函数内部的变量
2.另一个就是让这些变量始终保存在内存中
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000
result 实际就是闭包函数f2 :
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000
在这段代码中,result实际上就是闭包f2函数,它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。
为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。
这段代码中另一个值得注意的地方,就是”nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作
闭包的注意点
1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
14.箭头函数与普通函数的五个不同之处
- this不同,普通函数内部,this值(即执行上下文)是动态的,可以是window也可以是对象本身
箭头函数没有定义自己的执行上下文,一般是父级的对象
- this不同,普通函数内部,this值(即执行上下文)是动态的,可以是window也可以是对象本身
- 2.普通函数可以做构造函数,轻松构建对象,箭头函数不能用作构造函数
- 3.普通函数的主体内部有arguments,箭头函数没有arguments .arguments是类数组对象,包换已调用函数的参数列表
- 4.隐式return,箭头函数一条语句时可以省略return
- 5.再类中使用箭头函数定义方法,箭头函数绑定this到类的实例
15.简单介绍下 react 中的 diff 算法?
把树形结构按照层级分解,只比较同级元素。 给列表结构的每个单元添加唯一的 key 属性,方便比较。React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名 字) 合并操作,调用 component 的 setState 方法的时候, React 将其标记 为 dirty.到每一个事件循环结束, React 检查所有标记 dirty 的 component 重新绘制. 选择性子树渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性能。
16.什么是 Redux?
Redux 是一个状态管理工具, 不仅可以在 react 中使用, 也可在其他框 架中使用, 甚至可以脱离框架本身使用. redux 中有几个核心的组成部 分:
store 存储数据的对象,必须通过 createStore 方法来创建;
action 更新数据的规则, 必须有一个属性 state, 值必须是字符串;
reducer 更新数据的函数, 需要传入 state 状态数据和 action 更新规则. 在 react 中使用 redux 的时候, 一般会使用 react-redux 来简化使用步 骤
17.React 中如何操作 DOM?
在需要进行 dom 操作的标签上设置一个 ref 属性, 保证值不要重复, 后期在js 部分可以通过”this.refs.属性名”来获取标签的虚拟dom 对象
18.什么是高阶组件(HOC)?
函数的返回值是一个函数, 我们称之为高阶函数. 同理一个组件返回 值如果还是一个组件, 那么就称之为高阶组件. redux 中提供的 connect 就是一个高阶组件
19.react 性能优化可以使用哪个生命周期函数?
shouldComponentUpdate 这个方法用来判断是否需要调用 render 方 法重新描绘 dom。因为 dom 的描绘非常消耗性能,如果我们能在 shouldComponentUpdate 方法中能够写出更优化的 dom diff 算法, 可以极大的提高性能。
20.git 中有哪些常用的命令?
初始化仓库: git init
添加暂存区: git add 文件名
提交到本地仓库: git commit -m ‘注释‘
推送到远程仓库: git push 仓库地址 分支名称
拉取远程仓库代码: git pull
克隆仓库: git clone 仓库地址
创 建分支: git branch 分支名称
切 换分支: git checkout 分支名称
查 看分支: git branch
合并分支: git merge 分支名称
查 看日志: git log (git log –oneline)
查看所有日志: git reflog
版 本 回 退 : git reset –hard 版 本 号 (commit-id 可 以 通 过 git log –oneline 获取
21.git 和 svn 有什么不同?
git 是一个分布式仓库管理系统, 每个人本地都有一个本地仓库,svn 是 一个集中式仓库管理系统, 仓库只有一个. svn 一般需要服务端给每个 人分配账号和密码, git 是使用 ssh 公钥/秘钥对来区分不同程序员的
22.前端构建工具?
webpack , gulp , grunt
23.webpack 和 gulp 在进行代码合并的时候还有什么不同?
webpack 是基于 commonjs 模块化规范进行代码合并, 而 gulp 只是简 单的代码合并
const path=require('path');
const HtmlWebapckPlugin=require('html-webpack-plugin');
const htmlPlugin=new HtmlWebapckPlugin({
template:path.join( dirname,'src/index.html'),
filename:'index.html'
});
module.exports={
// 打包模式, 可值:development(开发模式),production(生产模式)
mode:'development',
// 插件配置节点
plugins:[
// html-webpack-plugin 作用:根据模板,在内存中创建一个 html 页面
htmlPlugin
],
resolve:{
// 配置省略的文件后缀
extensions: ['.js', '.jsx', '.json'],
// 配置根路径
alias:{'@':path.join( dirname,'./src')}
}
module:{
// 配置 loader
rules:[
{
test:/\.js|jsx$/,
use:'babel-loader',
exclude:/node_modules/
},
{
test: /\.scss$/,
use: [ 'style-loader',
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[name]-[local]-[hash:5]'
}
}
}, 'sass-loader' ] },
{
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
loader: 'url-loader', // 需 要 依 赖 file-loader
options: { limit: 10000 }
}
]
}
}
}
24.在 jsx 中如果非要创建多个平行标签, 该如何处理?
- 在 jsx 的最外层使用<> </>进行包裹;
- 或者使用<React.Fragment> </React.Fragment>标签进行包裹; 两种方式本质是一样的,
底层都是通过 document.createDocumentFragment()创建了一个虚拟 dom 标签
25.setState 什么时候是同步,什么时候是异步?
这里的“异步”不是说异步代码实现. 而是说 react 会先收集变更,然后 再进行统一的更新. setState 在原生事件和 setTimeout 中都是同步的. 在合成事件和钩子函数中是异步的. 在 setState 中, 会根据一个 isBatchingUpdates 判断是直接更新还是稍后更新, 它的默认值是 false. 但 是 React 在 调 用 事 件 处 理 函 数 之 前 会 先 调 用 batchedUpdates 这 个 函 数 , batchedUpdates 函 数 会 将 80 isBatchingUpdates 设置为 true. 因此, 由 react 控制的事件处理过程, 就变成了异步(批量更新).
26.什么是 ssr? 如何实现 ssr?
ssr 是全拼(server side rendering) ,中文意思, 服务端渲染, 让页面的渲 染在服务端完成, 生产环境必须部署nodeJS 的环境, 因为服务端渲染 必须借助 nodeJS 来完成. vue 中可以使用 nuxt 框架实现服务端渲染.
27.谈谈 async/await 的使用方式和场景
async 是用来修饰函数的声明, 使用async 修饰的函数会变成一个异步 函数. await 用来修饰函数的调用, 被 await 修饰的函数必须返回一个 promise 异步对象, 使用 await 修饰后, 就会将 promise 异步对象转换 成一个同步操作
28.你了解到的网站攻击方式有哪些?
常见的网站攻击方式有 xss(跨站脚本攻击), csrf(跨站请求伪造)
29.什么是页面的回流和重绘?
回流是指当页面的结构或者标签的尺寸发生变化的时候, 浏览器需 要对页面进行重排, 并重新渲染;
重绘是指当页面上的标签的外观(比如字体颜色,或背景颜色)发生改 变的时候, 浏览器需要重新对页面进行渲染. 所以回流一定会引起页面的重绘, 重绘不一定会引起回流.
要提高页面性能, 就要尽可能的减少页面的回流和重绘.
30.GET 和POST 的区别,何时使用 POST?
get 是将要传递的参数拼在 url 中进行传递,传递数据量少, 不安全 43 post 是将传递的参数放在请求体里传递, 携带数据量大, 相对安全. 要提交一些敏感数据(比如登录密码),上传文件时, 必须使用 post 请求
31.cookie, session,sessionStorage,localStorage
cookie和session都是用来跟踪浏览器用户身份的会话方式。
保持状态:cookie保存在浏览器端,session保存在服务器端
存储的大小:cookie:单个cookie保存的数据不能超过4kb;session大小没有限制。
存储内容:cookie只能保存字符串类型,以文本的方式;session通过类似与Hashtable的数据结构来保存,能支持任何类型的对象(session中可含有多个对象)
session的安全性大于cookie。
cookie断用户是否登陆过网站,以便下次登录时能够实现自动登录(或者记住密码)。如果我们删除cookie,则每次登录必须从新填写登录的相关信息。
(2)保存上次登录的时间等信息。
(3)保存上次查看的页面
(4)浏览次数
32.for循环和forEach区别
- 1.在固定长度或者长度不需要计算的时候for循环效率高于foreach,在不确定长度或者计算长度有损性能
的时候用foreach比较方便
- 2.foreach适用于只是进行集合或数组遍历,for则是在较复杂的循环中效率更高
- 3.如果对集合中的值进行修改,就要用for循环,foreach内部原理是iterator,但它不能像iterator一样可以人为控制,
- 4.forEach相比普通的for循环的优势在于对稀疏数组的处理,会跳过数组中的空位
- 5.foreach不能中断循环,for循环可以中断循环
33.Viewport(视口)的概念
pc端: viewport实际上等于浏览器窗口,拥有浏览器窗口的宽度和高度,document.documentElement.clientWidth获取。
移动端:
布局视口:pc端布局视口等于浏览器窗口的宽度,移动端上,要让pc端浏览器设计的网站能够完全显示在移动端的小屏幕里,此时布局视口会远大于移动设备的屏幕,就会出现滚动条
document.documentElement.clientWidth | document.body.clientWidth
视觉视口(visual viewport):visual viewport的宽度指的是浏览器可视区域的宽度
理想视口:布局视口的一个理想尺寸,只有当布局视口的尺寸等于设备屏幕的尺寸时,才是理想视口,
js获取理想视口:window.screen.width
34.visibility:hidden和display:none 的区别
1.作用不同
visibility:hidden ----将元素隐藏,但是在网页上的位置还是占着
display:none ------将元素的显示设置为无,即再网页中不占任何的位置
2.使用后html元素有所不同
visibility:hidden,使用后html元素仅仅再视觉上看不见(完全透明),而它所占据的空间位置,仍然存在,
也即是说它扔具有高度,宽度等属性值
display:none使用该属性后,html元素的宽度,高度等各种属性值都会"丢失"。
35.v-if和v-show的区别
v-if的原理是根据判断条件来动态的进行增删DOM元素,v-show是根据判断条件来动态显示和隐藏元素,
频繁的进行增删DOM操作会影响页面加载速度和性能。
36.浏览器的多线程
GUI渲染线程
JavaScript引擎线程
事件触发线程
定时触发器线程
异步http请求线程
GUI渲染线程:负责渲染浏览器页面html元素,解析html,css,构建DOM树和RenderObject树,布局和绘制等,当页面重绘重排时,该线程就会执行
JavaScript引擎线程: 也可以成js内核,只要负责处理JavaScript脚本程序
例如:V8引擎
GUI渲染线程与引擎线程是互斥的。
事件触发线程: 事件被触发时该线程会把事件添加到EventLoop(事件循环队列)的队尾,等待js引擎的处理
定时触发器线程: setInterval与setTimeout所在线程, 通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待js引擎空闲后执行)
异步http请求线程
在XMLHttpRequest在连接后是通过浏览器新开一个线程请求。
将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件
,将这个回调再放入事件队列中,再由JavaScript引擎执行37.宏任务(macrotask)和微任务(microtask)
先运行微任务,后运行宏任务
微任务的发起者是js引擎,事件有:Promise,process.nextTick(node.js),MutainObserver
宏任务的发起者是(Node,浏览器), 事件有setTimeout, setInterval, script(整体代码),setImmediate(Node.js环境)
console.log(‘script start’)
async function async1() {
await async2()
console.log(‘async1 end’)
}
async function async2() {
console.log(‘async2 end’)
}
async1()
setTimeout(function() {
console.log(‘setTimeout’)
}, 0)
new Promise(resolve => {
console.log(‘Promise’)
resolve()
})
.then(function() {
console.log(‘promise1’)
})
.then(function() {
console.log(‘promise2’)
})
console.log(‘script end’)
打印顺序为:
script start
async2 end
Promise
script end
async1 end
promise1
promise2
setTimeout
JS 运行机制为从上而下,首先打印script start,async/await 是Promise包装执行会立即执行async2()打印async2 end,把setTimeout加入宏任务队列但是不会立马执行,往下走,Promise创建属于同步任务此时打印Promise,并放入微任务队列中,再往下走直接打印script end,此时如果有微任务会优先执行微任务队列,微任务队列执行完毕再执行宏任务,async1 end 的打印是因为执行了Promise.then的方法,继续微任务输出promise1、promise2,当微任务队列为空,执行宏任务setTimeout,此时打印setTimeout。js分同步任务和异步任务
同步任务都在主线程上执行,行成一个执行栈
主线程之外,事件触发线程管理着一个任务队列,只要异步任务有了运行结果,就在任务队列之中放置一个事件
一旦执行栈中的所有同步任务执行完毕(js引擎空闲),系统就会读取任务队列,将可运行的异步任务添加到可执行栈中。开始执行
38.前端性能优化
1.减少http请求
2.使用服务端渲染
3.静态资源使用CDN
4.将css放在文件头部,JavaScript文件放在底部
5.使用字体图标代替图片图标
6.善用缓存
7.图片使用懒加载
> 客户端渲染: 获取html文件,根据需要下载JavaScript文件,运行文件,生成DOM,再渲染
>
> 服务端渲染:服务端返回HTML文件,客户端只需解析HTML
>
> css执行会阻塞渲染,阻止js执行
>
> js加载和执行会阻塞HTML解析,阻止CSSOM构建
39浏览器渲染过程
1.解析HTML生成DOM树
2.解析CSS生成CSSOM规则树
3.将DOM树与CSSOM规则树合并在一起生成渲染树
4.遍历渲染树开始布局,计算每个节点的位置大小信息
5.将渲染树每个节点绘制到屏幕
40.fetch请求和ajax请求的区别
1.ajax是XMLHttpRequest的一个实例,容易出现回调地狱
ajax请求:
//1.创建异步对象
var xhr = new XMLHttpRequest()
//2.设置请求行open(请求方式,请求url)
xhr.open("post","http://www.yangaoyuan.cn")
//3.设置请求头,get不需要设置,post需要设置请求头
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
//4.设置请求体,发送send()
xhr.send() //get请求
xhr.send("username="+name) //post请求
//5.让异步对象接收服务器的响应数据(数据成功返回并且响应状态为4)
xhr.onreadystatechange = function(){
if(xhr.status == 200 && xhr.readyState == 4){
console.log(xhr.responseText);
}
2.fetch请求
1.fetch是基于promise实现的,也可以结合async/await
2.fetch请求默认不带cookie,需要设置需要设置fetch(URL,{credentials:’include’})。Credentials有三种参数:same-origin,include,*
3.所有版本的IE均不支持原生Fetch
4.fetch是window的一个方法
fetch(url,{
method:'get'
}).then(function (response) {
return response.json() //执行成功第一步
}).then(function (returnedValue) {
//执行成功的第二步
}).catch(function (err) {
//中途的任何地方出错 都会在这里被捕获到
})
41.HTML几种定位方式
static(默认定位方式)
relative(相对定位方式)
absolute(绝对定位)
fixed(固定定位)
sticky(粘性定位)
父元素不能overflow:hidden或者overflow:auto属性。
必须指定top、bottom、left、right4个值之一,否则只会处于相对定位
父元素的高度不能低于sticky元素的高度
sticky元素仅在其父元素内生效以浏览器的可视窗口为参照点移动元素(固定定位特点)粘性定位占有原先的位置(相对定位特点)必须添加top.right.bottom,left其中一个才有效一般可跟页面滚动搭配使用
42.css隐藏元素的五种方法
1.opaticy:0;
2.visibility:hidden
3.display:none;
43清除浮动的几种方法
1.父级div overflow:hidden
2.父级div overflow:auto
3.6363结尾处添加div clear:both
44.async,await和Promise
1.执行async函数,返回的都是Promise
async函数如果返回一个普通值,将会包装成promise类型返回,
asynch函数如果返回的是一个promise类型,将直接返回
async function test1(){
return 1;
}
async function test2(){
return Promise.resolve(2);
}
const result1 = test1();
const result2 = test2();
console.log('result1',result1)
console.log('result2',result2);
2.promise.then成功的情况对应await
async function test3(){
const p3 = Promise.resolve(3);
p3.then(data=>{
console.log('data',data);
})
const data = await p3;
console.log('data',data);
}
test3();
async function test4(){
const data4 = await 4; //等价于 await Promise.resolve(4);
console.log('data4',data4);
}
test4();
async function test5(){
const data5 = await test1(); //等价于 await Promise.resolve(4);
console.log('data5',data5);
}
test5();
- //Promise.catch异常情况对应try…catch
async function test6(){
const p6 = Promise.reject(6);
try{
const data6 = await p6;
console.log(‘data6’,data6);
}catch(e){
console.error(‘e’,e);
}
}
test6();
路由中传参:
1..methods传参 /dest/${id}
2.params传参 :/id
3.query传参 ?/id
45new运算符做了什么?
- 1.创建一个新对象(空对象)
- 2.将新对象的_proto指向构造函数的原型
- 3.将构造函数的this指向新对象
- 4.根据返回值判断,是否返回新对象