锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

前端面试题整理

时间:2023-02-21 17:30:01 40针前置连接器6es72d型位移变送器

js原生

map和foreach的区别 **

2.2.1、forEach()返回值是undefined,不能链式调用。
2.2.2、map()返回新数组,原数组不会改变。
2.2.3.无法终止或跳出forEach()循环,除非抛出异常,否则要执行数组是否符合要求,返回布尔值,可以使用一般for循环实现,或使用Array.every()或者Array.some();
2.2.4、$.each()方法规定每个匹配元素规定的运行函数可以返回 false 可用于早期停止循环。
https://www.jianshu.com/p/83aa9a2a4055

5、解释下JavaScript中this如何工作。 ****

this永远指向函数运行时的对象,而不是函数创建时的对象。匿名函数或不在任何对象中的函数指向window 。
1.如果是call,apply,with,指定的this谁就是谁。
2.普通函数调用,谁调用函数,this就是谁。

异步线程、轮询机制、宏任务微任务 ****

https://blog.csdn.net/u013362969/article/details/89714436
https://www.cnblogs.com/ckAng/p/11133643.html
https://zhuanlan.zhihu.com/p/33058983

阻止冒泡 **

w3c方法是ev.stopPropagation()
IE中方法是window.event.cancelBubble = true

防止默认事件 **

ev.preventDefault()
return false;///写在函数的最后一句

02.怎样判断array 和 object ***

https://www.jianshu.com/p/898d860497ed

-01 隐式转换数据类型 **

https://www.jianshu.com/p/7cb41d109b7e

01 Div里面有一个div *****

1.有几种方法可以水平垂直居中 https://www.cnblogs.com/a-cat/p/9019184.html
回答后会继续问
2、当里面div框架高度不固定时,如何水平垂直居中 https://www.jb51.net/css/56268.html

说说盒子模型 ****

布局时使用,div ,div的 margin padding border
普通盒模型和怪盒模型的区别
ie 与其他浏览器他浏览器对齐 margin 和 padding分析不同

11 算法,一个数组000001111111111111,这样,你怎么能找到第一个1,最底层?js原生写法, 例如,当第一个数字与第二个数字进行比较时,当第二个大于第一个元素时,就会发现第一个1。有没有更高效的写作方法?

利用循环或递归实现

12 对象的key能使数字吗? *

可以是数字,object对应的key没有限制,只是如果是数字,取值的时候就不能用英文句号(.),只能用[]取值。

1. async await 和promise和generator有什么区别 ****

这些都可以解决异步操作的地狱回调问题
async await 和promise对象差异:
async和promise都是异步法,区别在于async结果是promise对象,async是promise的终结版。
await只能在async中使用,await阻塞意味着暂停。您共同调用两个接口。第一个执行后,不输出结果。在返回这两个结果之前,您必须等待第二个接口执行。
将异步操作转化为同步操作的做法

async await和generator:
async是Generator的语法糖 ,也就是说,async是对generator的实现,而generator代码更复杂。
generator 除解决回调区域问题外,还可作为迭代器使用。generator 语法一般用于语法redux-saga
redux-saga 一般在umi或dva框架中使用

2.手写promise ***

new Promise(
function (resolve, reject) {
// 一段耗时的异步操作
resolve(‘成功’) // 完成数据处理
// reject(‘失败’) // 数据处理错误
}
).then(
(res) => {console.log(res)}, // 成功
(err) => {console.log(err)} // 失败
)
/******************/
const promiseClick =()=>{
console.log(调用‘点击方法’)
let p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log(执行完成Promise’);
resolve(任何数据可以返回,如接口返回数据);
}, 2000);
});
return p
}
promiseClick().then(()=>{
///成功回调
},()=>{
///回调失败
});

new Promise(function(resolve,reject){
//返回resolve还是reject
}).then(function(){
//成功回调接收
},function(){
//接收失败回调
})

3.promise.all作用 ***

Promise.all(iterable) 方法返回一个 Promise 例子,这个例子在 iterable 所有参数 promise 都“完成(resolved)”或
不包括参数 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),这个例子回调失败了(reject),
失败的第一个原因是失败 promise 的结果。
它通常用于启动多个异步任务并发运行,并为其结果创建承诺,以便人们能够等待所有任务完成。
流行说法:解决promise同步调用问题可以将多个异步操作转化为同步操作。缺点:只要有一个promise返回错误,那么后面的promise不再执行

const promise1 = Promise.resolve(3); const promise2 = 42; const promise3 = new Promise((resolve, reject) => {   setTimeout(resolve, 100, 'foo'); }); Promise.all([promise1, promise2, promise3]).then((values) => {   console.log(values); }); 

promise.allsettled

4.什么是工厂模式,有什么优缺点? *

工厂模造对象,工厂模式是一种设计模式,通常在类或类的静态方法中实现,
有下列目的:创建类似对象时,执行重复操作
当编译不知道具体类型时,为工厂客户提供创建对象的界面

////用工厂创建一个对象    function createPerson(name,sex){     //1.原料     var obj = new Object();     //2.加工  -- 赋值属性     obj.name = name;     obj.sex = sex;     //3.方法     obj.showName = function(){      console.log("人物名称:" this.name);     }     obj.showSex = function(){      console.log("性别:性别:" this.sex);     }     //4.加工结束,--输出返回     return obj;     }    //使用工厂模式    var person1 = createPerson("如花","男");    ////调用工厂的方法    person1.showName();    person1.showex();
			var person2 = createPerson("凤姐","女");
			//调用工厂里的方法
			person2.showName();
			person2.showSex();
			/*
			工厂模式:
			优点: 写好了工厂方法后,只要原料足够,我们可以无限次的创建新的对象
			缺点: 1.没有使用 new ,2.每个对象都有自己的函数,浪费资源

接触过哪些设计模式: 工厂模式 、单例模式(数据库连接)、观察者模式(双向绑定原理)、订阅模式、mvc模式、mvvm模式

5.图片/文件夹上传到后台是什么类型? *

图片上传后台有三种格式:

  1. file格式 (创建formData来完成file上传)
 var formData = new FormData();
                    $.each($(‘#imgfile‘)[0].files, function (i, file) {
                        formData.set(‘idcard‘, file);   //idcard  字段 根据自己后端接口定
                    });
                    //processData: false, contentType: false,多用来处理异步上传二进制文件。
                    that.$indicator.open();
                    $.ajax({
                        url: ‘http://wjtest.jecinfo.cn:9090/indentity/check‘,
                        type: ‘POST‘,
                        data: formData,                    // 上传formdata封装的数据
                       ....
                        }
  1. base64格式

var base64Pic = ‘‘
document.getElementById(‘imgfile‘).onchange = function(){
      var fileReader = new FileReader();
      fileReader.readAsDataURL(this.files[0]);
      fileReader.onload = function(){
          base64Pic = fileReader.result;
          console.log(base64Pic )  //base64   可以直接放在src上 预览
      }

3.Blob流格式

6.原生基础数据类型和引用数据类型的区别 *

1.栈(stack)和堆(heap)stack为自动分配的内存空间,它由系统自动释放;而heap则是动态分配的内存,大小也不一定会自动释放。
2.基本的数据类型:String, Number, boolean, Null, Undefined,Symbol(ES6新增)  *****
  特点: 存储的是该对象的实际数据,(存放在栈中)
3.对象数据类型(也称为引用数据类型):Array,Object,Function
  特点: 存储的是该对象在栈中引用,真实的数据存放在堆内存里,(存放在堆内存中的对象,每个空间大小不一样,要根据情况进行特定的配置)
注:在JS中除了基本数据类型以外的都是对象,数据是对象,函数是对象,正则表达式是对象

7.深浅拷贝: ****

1、区别: 浅拷贝/深度拷贝
判断: 拷贝是否产生了新的数据还是拷贝的是数据的引用
知识点:对象数据存放的是对象在栈内存的引用,直接复制的是对象的引用

2、常用的拷贝技术
for循环完成深拷贝
二、深拷贝
1、js数组的slice方法
var arr1 = [“前端”,“安卓”,“苹果”];
var arr2 = arr1.slice(0);
arr2[0] = “后端”;
console.log(“原始值:” + arr1 );//前端,安卓,苹果
console.log(“新值:” + arr2);//后端,安卓,苹果
理解:通过JS的slice方法,改变拷贝出来的数组的某项值后,对原来数组没有任何影响。
缺点:适用于对不包含引用对象的一维数组的深拷贝
2、js数组的concat方法
var arr1 = [“前端”,“安卓”,“苹果”];
var arr2 = arr1.concat();
arr2[0] = “后端”;
console.log(“原始值:” + arr1 );//前端,安卓,苹果
console.log(“新值:” + arr2);//后端,安卓,苹果
理解:concat方法,原数组和新数组修改某值后,不会改变。
缺点:适用于对不包含引用对象的一维数组的深拷贝

1). arr.concat(): 数组深拷贝
  2). arr.slice(): 数组深拷贝
  3).Object.assign()对象深拷贝
  4). JSON.parse(JSON.stringify(arr/obj)): 数组或对象深拷贝, 但不能处理函数数据
  5). 浅拷贝包含函数数据的对象/数组
  6). 深拷贝包含函数数据的对象/数组
对于多层对象和数组:可以使用 递归调用、JSON.parse(JSON.stringify(arr/obj))、jquery的extend方法来实现深拷贝

https://blog.csdn.net/xuexizhe88/article/details/80990529
https://www.cnblogs.com/echolun/p/7889848.html

8.弹性布局。浮动布局 table布局 *****

弹性布局:使用 百分比、rem 、flex 自适应布局
浮动布局:使用 float clear
table布局:一般用于后台显示
自适应布局和响应式布局:一般需要用到media媒体查询完成,需要根据屏幕宽度的不同,写多个css样式文件

9.flex 的水平居中和垂直居中 ****

水平:justify-content:center; 垂直:align-content:center;
flex:1 的值是1 1 0%,【父控件有剩余空间占1份放大,父控件空间不足按1缩小,自身的空间大小是0%】 ***
flex属性 是 flex-grow、flex-shrink、flex-basis三个属性的缩写。
推荐使用此简写属性,而不是单独写这三个属性。
flex-grow:定义项目的的放大比例;
默认为0,即 即使存在剩余空间,也不会放大;
所有项目的flex-grow为1:等分剩余空间(自动放大占位);
flex-grow为n的项目,占据的空间(放大的比例)是flex-grow为1的n倍。
flex-shrink:定义项目的缩小比例;
默认为1,即 如果空间不足,该项目将缩小;
所有项目的flex-shrink为1:当空间不足时,缩小的比例相同;
flex-shrink为0:空间不足时,该项目不会缩小;
flex-shrink为n的项目,空间不足时缩小的比例是flex-shrink为1的n倍。
flex-basis: 定义在分配多余空间之前,项目占据的主轴空间(main size),浏览器根据此属性计算主轴是否有多余空间,
默认值为auto,即 项目原本大小;
设置后项目将占据固定空间。
所以flex属性的默认值为:0 1 auto (不放大会缩小)
flex为none:0 0 auto (不放大也不缩小)
flex为auto:1 1 auto (放大且缩小)

10.闭包 *****

闭包定义:闭包就是能够读取其他函数内部变量的函数。
闭包可以就解决全局作用域污染的问题
闭包使用场景,闭包的应用场景:
1.setTimeout
  原生的setTimeout传递的第一个函数不能带参数,通过闭包可以实现传参效果。

 function f1(a) {
     function f2() {
         console.log(a);
     }
     return f2;
 }
 var fun = f1(1);
 setTimeout(fun,1000);//一秒之后打印出1

2.回调
  定义行为,然后把它关联到某个用户事件上(点击或者按键)。代码通常会作为一个回调(事件触发时调用的函数)绑定到事件。

   12
     

3.函数防抖 ***
  在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
   实现的关键就在于setTimeOut这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现。

 // fn [function] 需要防抖的函数
 // delay [number] 毫秒,防抖期限值
 
 function debounce(fn,delay){
     let timer = null
     //借助闭包
     return function() {
         if(timer){
             clearTimeout(timer) //进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
             timer = setTimeOut(fn,delay) 
         }else{
             timer = setTimeOut(fn,delay) // 进入该分支说明当前并没有在计时,那么就开始一个计时
         }
     }
 }

4.封装私有变量
  如下面代码:用js创建一个计数器

 function f1() {
     var sum = 0;
     var obj = {
        inc:function () {
            sum++;
            return sum;
        }
 };
     return obj;
 }
 let result = f1();
 console.log(result.inc());//1
 console.log(result.inc());//2
 console.log(result.inc());//3

所有js数据类型都拥有valueOf和toString这两个方法,null除外valueOf()方法:返回指定对象的原始值。
toString()方法:返回对象的字符串表示。在数值运算中,优先调用了valueOf,字符串运算中,优先调用toString. sum+’ '是一个字符串类型的数据

 function f1() {
     var sum = 0;
     var obj = {
        inc:function () {
            sum++;
            return sum;
        }
 };
     return obj;
 }
 let result = f1();
 console.log(result.inc());//1
 console.log(result.inc());//2
 console.log(result.inc());//3

闭包产生问题:容易产生内存泄漏 (原因:闭包使用时,扩展了他变量的原有作用域,使变量常驻内存)
内部函数 被 外部函数 包含时,内部函数会将外部函数的局部活动对象添加到自己的作用域链中。

 outerFun(outerArgument){
     //被包含的内部函数可以访问外部函数的变量
     return function(){  
         return outerArgument+1
     } 
 } 

而由于内部匿名函数的作用域链 在引用 外部包含函数的活动对象 ,即使outFun执行完毕了,它的活动对象还是不会被销毁!
即,outerFun的执行环境作用域链都销毁了,它的活动对象还在内存中留着呢。
并且根据垃圾回收机制,被另一个作用域引用的变量不会被回收。
所以,除非内部的匿名函数解除对活动变量的引用(解除对匿名函数的引用),才可以释放内存。

 // 创建函数 还未调用
 var creatFun = outerFun(7)
 // 调用函数
 var result = creatFun(8)
 // 解除对匿名函数的引用
 creatFun = null

所以,闭包会造成内存泄漏,就是因为它把外部的包含它的函数的活动对象也包含在自己的作用域链中了,会比一般的函数占用更多内存。
怎样解决:在退出函数之前,将不使用的局部变量全部删除。可以使变量赋值为null;

 window.onload = function(){
         var el = document.getElementById("id");
         el.onclick = function(){
             alert(el.id);
         }
     }
     解决方法为
     window.onload = function(){
         var el = document.getElementById("id");
         var id = el.id;                                      //解除循环引用
         el.onclick = function(){
             alert(id); 
         }
         el = null;                                          // 将闭包引用的外部函数中活动对象清除
     }

循环使用闭包会有什么问题:在循环中使用闭包容易产生每个 i都有自己的独立作用于,导致输出结果都是循环的最后的值这种问题

 //循环里面包含闭包函数
 function box(){
     var arr = [];
     for(var i=0;i<5;i++){
         arr[i] = function(){
             return i;                            //由于这个闭包的关系,他是循环完毕之后才返回,最终结果是4++是5
         }                                        //这个匿名函数里面根本没有i这个变量,所以匿名函数会从父级函数中去找i,
     }                                            //当找到这个i的时候,for循环已经循环完毕了,所以最终会返回5
     return arr;
 }
 //alert(box());                                    //执行5次匿名函数本身
 //alert(box()[1]);                   //执行第2个匿名函数本身
 //alert(box().length);                            //最终返回的是一个数组,数组的长度为5
 alert(box()[0]());  

闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见的方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
在for循环里面的匿名函数执行 return i 语句的时候,由于匿名函数里面没有i这个变量,所以这个i他要从父级函数中寻找i,
而父级函数中的i在for循环中,当找到这个i的时候,是for循环完毕的i,也就是5,所以这个box得到的是一个数组[5,5,5,5,5]。
解决方法:

 function box(){
     var arr = [];
     for(var i=0;i<5;i++){
         arr[i] = (function(num){                    //自我执行,并传参(将匿名函数形成一个表达式)(传递一个参数)
             return num;                            //这里的num写什么都可以                    
         })(i);                                    //这时候这个括号里面的i和上面arr[i]的值是一样的都是取自for循环里面的i                            
     }                                            
     return arr;
 }
 //alert(box());                                
 //alert(box()[1]);
 //alert(box().length);                            
 alert(box()[0]);  

11.什么是内存泄漏,都什么情况容易产生内存泄漏 **

内存泄漏:即为变量内容持续占用内存空间,不释放,垃圾回收机制也没有将该内存回收的情况
死循环
定时器没有清除
绑定的事件没有解除
递归调用没有结束条件

主要存在内存泄漏的问题点
BOM DOM对象泄漏
scipt中存在对BOM DOM对象的引用
javaScript对象泄漏
闭包函数导致的泄漏
3、主要关注的代码点
DOM中的addEventLisner 函数及派生的事件监听, 比如Jquery 中的on 函数, vue 组件实例的 $on 函数,第三方库中的初始化函数
BOM对象的事件监听,比如webSocket的监听事件
避免不必要的函数引用
如果是要render函数,避免在html
标签中DOM BOM事件

12.原型 ,原型链,继承的方式 *****

原型:既构造函数的prototype.每个构造函数都有一个prototype属性指向生成这个函数的原型对象,简称原型;
prototype 可以对构造函数进行扩展,既添加构造函数的属性和方法
原型链:每个对象都有一个__proto__属性, 指向生成改对象的原型对象,这样,我们就可以找到是哪个对象生成了改对象,
原型链一般用于继承
原型链的核心就是依赖对象的_proto_的指向,当自身不存在的属性时,就一层层的扒出创建对象的构造函数,直至到Object时,就没有_proto_指向了。
因为_proto_实质找的是prototype,所以我们只要找这个链条上的构造函数的prototype。其中Object.prototype是没有_proto_属性的,它==null。

 function Person(name){
             this.name = name;
      }
      var p = new Person();
      //p ---> Person.prototype --->Object.prototype---->null
 

原型继承

//原型继承的基本案例
function Person(name, age) {
	this.name = name;
	this.age = age;
}
//1.直接替换原型对象 
var parent = {
	sayHello : function() {
		console.log("方式1:替换原型对象");
	}
}
Person.prototype = parent;
var p = new Person("张三", 50);
p.sayHello();
//2.混入式原型继承
console.log(".............混入式原型继承..............");
function Student(name, age) {
	this.name = name;
	this.age = age;
}
var parent2 = {
	sayHello : function() {
		console.log("方式2:原型继承之混入式加载成员");
	}
}
for ( var k in parent2) {
	Student.prototype[k] = parent2[k];
}
var p = new Student("张三", 50);
p.sayHello();

继承的方式:

13. this指向 ,箭头函数的this指向 ****

this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象

15. 使用node.js 创建本地服务器 *

16. Git常用命令 *****

git init 初始化 *****
git clone 克隆代码库 *****
git config 配置
git add 增加文件到暂存区 *****
git commit 提交暂存区到仓库 *****
git branch 名称 新建分支 *****
git checkout 切换分支 *****
git merge 合并分支 *****
git branch -d 删除分支 *****
git tag 打tag 包 *****
git status 查看状态 *****
git log 查看日志 *****
git diff 查看暂存区和工作区差异
git fetch 下载远程仓库的变动 *****
git pull 取回远程仓库变化,并与本地分支合并 *****
git push 上传本地指定分支到远程仓库 *****
解决冲突:

17. 跨域的解决方案 *****

因为前端有同源保护政策,所以,不同源或者说不同的域名和ip之间不能进行访问。

1.jsonp jsonp有什么问题?只能是get方式不能是post方式 jsonp原理:script标签的src属性可以跨域
2.proxy代理 只能是打包前使用,打包后需要后台配置跨域 nginx反向代理
3.后台头部设置 Access-Control-Allow-Origin ,cors
4.其他 方式:
a. document.domain + iframe (只有在主域相同的时候才能使用该方法)
b. location.hash + iframe
c. window.name + iframe
d. postMessage(HTML5中的XMLHttpRequest Level 2中的API)
e. web socket
web sockets是一种浏览器的API,它的目标是在一个单独的持久连接上提供全双工、双向通信。

18. for循环定时器打印产生问题,怎么解决 ** js异步轮询机制

for(var i = 1; i <= 5; i++){
setTimeout(function () {
console.log(i);
}, 1000);
}
打印结果为5个6;
原因是:js是单线程,有任务队列,任务队列分为两种,同步任务和异步任务。
同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
所以循环是同步任务先执行,当执行完之后,当setTimeout的异步操作准备好后,通知主线程,主线程将其从异步队列中取出来,再执行,所以当循环完成时,i的值位6,setTimeout再执行,打印5个6

所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
主线程不断重复上面的第三步。
只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。这个过程会不断重复。
"任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。
事件循环(event loop)
主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。

19. http协议详解 http请求方式有 http响应状态码 *****

1.http 特点:
1.支持客户/服务器模式。
2.简单快速:。
3.灵活:
4.无连接:
5.无状态:

  1. http请求由三部分组成,分别是:请求行、消息报头、请求正文
    请求方法(所有方法全为大写)有多种,各个方法的解释如下:
    GET 请求获取Request-URI所标识的资源
    POST 在Request-URI所标识的资源后附加新的数据
    HEAD 请求获取由Request-URI所标识的资源的响应消息报头
    PUT 请求服务器存储一个资源,并用Request-URI作为其标识
    DELETE 请求服务器删除Request-URI所标识的资源
    TRACE 请求服务器回送收到的请求信息,主要用于测试或诊断
    CONNECT 保留将来使用
    OPTIONS 请求查询服务器的性能,或者查询与资源相关的选项和需求

3.在接收和解释请求消息后,服务器返回一个HTTP响应消息。
HTTP响应也是由三个部分组成,分别是:状态行、消息报头、响应正文
3xx:重定向–要完成请求必须进行更进一步的操作
4xx:客户端错误–请求有语法错误或请求无法实现
5xx:服务器端错误–服务器未能实现合法的请求

301 永久移动,请求的资源被永久的移动到新url,返回信息会包括新的url。浏览器会自动定向到新url
302 临时移动,资源只是临时被移动,客户端赢继续使用原有url
304 未修改,所请求的资源未修改,服务器返回此状态码是=时,不会返回任何资源,客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源

400 Bad Request //客户端请求有语法错误,不能被服务器所理解,解决方法:修改请求的参数及语法
401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 ,
解决方式:即没有启用任何认证方式,只需要在IIS Manager里面启用需要的认证方式即可。
即被Authorization Rule阻挡,则需要分析这个authorization rule是否是否必须来决定对他的更改。
403 Forbidden //服务器收到请求,但是拒绝提供服务
  1、你的IP被列入黑名单。
  2、你在一定时间内过多地访问此网站(一般是用采集程序),被防火墙拒绝访问了。
  3、网站域名解析到了空间,但空间未绑定此域名。
  4、你的网页脚本文件在当前目录下没有执行权限。
  6、以http方式访问需要ssl连接的网址。
  7、浏览器不支持SSL 128时访问SSL 128的连接。
  8、在身份验证的过程中输入了错误的密码。
解决方式: 1、重建dns缓存
  对于一些常规的403 forbidden错误,马海祥建议大家首先要尝试的就是重建dns缓存,在运行中输入cmd,然后输入ipconfig /flushdns即可。如果不行的话,就需要在hosts文件里把主页解析一下了。
  2、修改文件夹安全属性
  3、关于apache导致的403 forbidden错误,需设置Apache的配置文件。
  4、关于HawkHost空间出现403 Forbidden错误需设置htaccess文件。
404 Not Found //请求资源不存在,eg:输入了错误的URL 解决办法:输入正确的url地址
405 请求方式不对 ,比如原本需要post方式请求的,你写了get方式请求

20. 一个页面从发送http请求到渲染页面的全过程(http事务流程)***

域名解析 --> 发起TCP的3次握手 --> 建立TCP连接后发起http请求 --> 服务器响应http请求,浏览器得到html代码
–> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户
https://www.cnblogs.com/xiaohuochai/p/9193083.html

21.tcp和udp的区别 *

TCP与UDP区别总结:
1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付

3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的

UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)

4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

5、TCP首部开销20字节;UDP的首部开销小,只有8个字节6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

##22.什么是长连接 *
在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。
当客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web资源(如JavaScript文件、图像文件、CSS文件等),
每遇到这样一个Web资源,浏览器就会重新建立一个HTTP会话。
而从HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加入这行代码:
Connection:keep-alive
在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时
,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个
时间。实现长连接需要客户端和服务端都支持长连接。

23.ajax是同步还是异步,ajax的流程 *****

ajax是异步的,
流程:
(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象.
(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息
(3)设置响应HTTP请求状态变化的函数.
(4)发送HTTP请求 .(send)
(5)获取异步调用返回的数据.(onreadystatechange)
(6)使用JavaScript和DOM实现局部刷新.

24.h5新特性 ***

1.语义化标签

4.Canvas绘图 ***

var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");//获取2d作图对象
cxt.moveTo(10,10);//画线的的起始点
cxt.lineTo(150,50);//画线
cxt.lineTo(10,50);
cxt.stroke();//线
cxt.fillStyle="#FF0000";//填充颜色
cxt.beginPath();//开始路径
cxt.arc(70,18,15,0,Math.PI*2,true);//画圆
cxt.closePath();//结束路径
cxt.fill();//填充
cxt.drawImage(img,0,0);//画布填充图片
cxt.createLinearGradient(0,0,175,50); //画布填充渐变

5.SVG绘图
6.地理定位 ***
百度地图引入和使用
7.拖放API ***
draggable=“true”
setData()
drag ondrag 当拖动元素或选中的文本时触发。
dragend ondragend 当拖拽操作结束时触发 (比如松开鼠标按键或敲“Esc”键). (见结束拖拽)
dragenter ondragenter 当拖动元素或选中的文本到一个可释放目标时触发(见 指定释放目标)。
dragexit ondragexit 当元素变得不再是拖动操作的选中目标时触发。
dragleave ondragleave 当拖动元素或选中的文本离开一个可释放目标时触发。
dragover ondragover 当元素或选中的文本被拖到一个可释放目标上时触发(每100毫秒触发一次)。
dragstart ondragstart 当用户开始拖动一个元素或选中的文本时触发(见开始拖动操作)。
drop ondrop 当元素或选中的文本在可释放目标上被释放时触发(见执行释放)。

8.Web Worker
9.Web Storage *****
特性
Cookie 一般由服务器生成,可设置失效时间,(设置过期时间是小于当前时间)。
如果在浏览器端生成Cookie,默认是关闭浏览器后失效;大小 4K左右
每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 需要程序员自己封装,源生的Cookie接口不友好

localStorage 除非被清除,否则永久保存 大小 5M 仅在客户端(即浏览器)中保存,不参与和服务器的通信
源生接口可以接受,亦可再次封装来对Object和Array有更好的支持

sessionStorage 仅在当前会话下有效,关闭页面或浏览器后被清除 大小 5M 仅在客户端(即浏览器)中保存,不参与和服务器的通信
源生接口可以接受,亦可再次封装来对Object和Array有更好的支持

COOKIE是如何工作的? *

Cookie可用于客户端数据的存储,在没有其它存储办法时,使用这种方式是可行的,但随着现在浏览器开始支持各种各样
的存储方式而逐渐被废弃。 由于服务器指定Cookie以后浏览器的每次请求都会携带Cookie数据,这会带来额外的性能负
担(尤其是在移动环境下)。 新的浏览器API已经允许开发者直接在本地存储数据,如可以使用Web storage API (本地
存储和会话存储)和IndexedDB(索引数据库)。
COOKIE主要用在以下三个方面:
会话状态管理(如用户登录状态、购物车)
个性化设置(如用户自定义设置)
浏览器行为跟踪(如跟踪分析用户行为)

COOKIE的缺陷
每个 HTTP 请求中都包含 Cookies,从而导致传输相同的数据减缓我们的 Web 应用程序。
每个 HTTP 请求中都包含 Cookies,从而导致发送未加密的数据到互联网上,可能会导致数据泄露,虽然进行过加密,但是攻击者拿到cookie后仍然可以登录,因为难以识别是否为同一个用户在登陆。
Cookies 只能存储有限的 4KB 数据,对于复杂的存储需求来说是不够用的。

sessionStroage有哪些应用场景?
答: 在不需要和服务器交互的场所,用来存储用户数据之类的,可以在路由页跳转的时候取出更改储存,减少调用接口的次数,减轻服务器压力。
用storage怎么来判断用户是否需要再登陆?
答:可以用加密的方法存储,每次用户访问的时候可以取出调用服务器接口作为参数发送进行对比,存在账号密码就直接跳过登录页。
localStorage是否可以在同源窗口共享?
答:同一浏览器的相同域名和端口的不同页面间可以共享相同的 localStorage,但是不同页面间无法共享sessionStorage的信息。

10.WebSocket

25.css3新特性 *** 动画效果

css3选择器 https://blog.csdn.net/weixin_42568381/article/details/81738566
border-radius
border-image
background-size
background-origin
background-clip:规定背景的绘制区域。
linear-gradient():线性渐变。
radial-gradient():径向渐变。
word-break:定义如何换行。
word-wrap:允许长的内容可以自动换行。
text-overflow:指定当文本溢出包含它的元素,应该发生什么。
text-shadow:文字阴影。
transform-style:指定嵌套元素是怎样在三维空间中呈现。
2D转换方法
rotate(angle):定义 2D 旋转,在参数中规定角度。
translate(x,y):指定元素在二维空间中的位移。X轴方向向右,Y轴方向向下。
scale(n):定义 2D 缩放转换。
matrix(a,b,c,d,e,f):定义 2D 转换,使用六个值的
矩阵
skew(x-angle,y-angle):定义沿着 X 和 Y 轴的 2D 倾斜转换。
perspective(n):为 3D 转换元素定义透视视图。
translate:指定元素在的位移。
matrix3d(n,n,n,n,n,n,n,n,n,n,n,n,n,n,n,n):定义 3D 转换,使用 16 个值的 4x4 矩阵。
过渡
transition:设置元素当过渡效果,四个简写属性为: *****
animation:为元素添加动画,是一个简写属性。 *****
css新增的一些伪类
1、p:first-of-type 选择器匹配属于其父元素的特定类型的首个子元素的每个元素。
2、p:last-of-type 选择器匹配属于其父元素的特定类型的最后一个子元素的每个元素。
3、p:only-of-type 选择器匹配属于其父元素的特定类型的唯一子元素的每个元素。
4、p:only-child 选择器匹配属于其父元素的唯一子元素的每个元素。
5、p:nth-child(2) 选择器匹配属于其父元素的第 N 个子元素,不论元素的类型。n 可以是数字、关键词或公式。
6、:enabled :disabled表单控件的禁用状态。
7、:checked:checked 选择器匹配每个选中的输入元素(仅适用于单选按钮或复选框)。
Flex弹性布局 *****
媒体查询 media *

26.es6新特性 *****

let const *****
变量的解构赋值 *****

let [a, b, c] = [1, 2, 3];
let [head, ...tail] = [1, 2, 3, 4];
let { foo, bar } = { foo: "aaa", bar: "bbb" };

字符串扩展

let text='abcdefg';
for (let i of text) {
  console.log(i);
}
includes():返回布尔值,表示是否找到了参数字符串。
startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。
repeat方法返回一个新字符串,表示将原字符串重复n次。
padStart()用于头部补全,padEnd()用于尾部补全。
模板字符串 `aaa{$test}`

数值的扩展:

Number.isFinite()用来检查一个数值是否为有限的(finite)。
Number.isNaN()用来检查一个值是否为NaN。
Number.parseInt(),转整型
 Number.parseFloat()转浮点型
 Number.isInteger()用来判断一个值是否为整数
 Math.trunc方法用于去除一个数的小数部分,返回整数部分。
 Math.sign方法用来判断一个数到底是正数、负数、还是零。
 Math.cbrt方法用于计算一个数的立方根。
 Math.sign()用来判断一个值的正负,但是如果参数是-0,它会返回-0。
 ES2016 新增了一个指数运算符(**)。

数组的扩展:

Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)。
Array.of方法用于将一组值,转换为数组。
Array.prototype.copyWithin(target, start = 0, end = this.length)数组实例的copyWithin方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。
数组实例的find方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。
fill方法使用给定值,填充一个数组。
entries(),keys()和values()——用于遍历数组。它们都返回一个遍历器对象(详见《Iterator》一章),可以用for...of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。
Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似。该方法属于ES7,但Babel转码器已经支持。

函数的扩展:

函数参数的默认值
与解构赋值默认值结合使用
函数的 length 属性
指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数。也就是说,指定了默认值后,length属性将失真
ES6 引入 rest 参数(形式为“...变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
扩展运算符 ...   *****
替代数组的apply方法 
// ES5的写法
Math.max.apply(null, [14, 3, 77])

// ES6的写法
Math.max(...[14, 3, 77])

// 等同于
Math.max(14, 3, 77);

扩展运算符的应用:合并数组 与解构赋值结合 函数的返回值 字符串 实现了Iterator接口的对象 Map和Set结构,Generator函数


/************/
严格模式 'use strict';
重点掌握,重点重点
箭头函数  ES6允许使用“箭头”(=>)定义函数。 箭头函数可以保留this的指向   *****
箭头函数注意点:
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作Generator函数。

对象的扩展:

Object.is() 比较两个值是否相等
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
属性的遍历
ES6一共有5种方法可以遍历对象的属性。
(1)for...in
for...in循环遍历对象自身的和继承的可枚举属性(不含Symbol属性)。
(2)Object.keys(obj)
Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)。
(3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有Symbol属性。
(5)Reflect.ownKeys(obj)
Reflect.ownKeys返回一个数组,包含对象自身的所有属性,不管是属性名是Symbol或字符串,也不管是否可枚举。
Object.setPrototypeOf方法的作用与__proto__相同,用来设置一个对象的prototype对象,返回参数对象本身。它是 ES6 正式推荐的设置原型对象的方法。
该方法与Object.setPrototypeOf方法配套,用于读取一个对象的原型对象。
Object.keys()引入了Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。
Object.values方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
Object.entries方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。

set 和 map 数据类型 *****

set可以用于数组去重,是无序的,set中不包含重复的元素
map 的key值可以是数组对象字符串等格式
Map类似于一个对象,是键值对的集合,键值可以是字符串,各种类型,对象。

proxy ***


Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”
var obj = new Proxy({}, {
  get: function (target, key, receiver) {
    console.log(`getting ${key}!`);
    return Reflect.get(target, key, receiver);
  },
  set: function (target, key, value, receiver) {
    console.log(`setting ${key}!`);
    return Reflect.set(target, key, value, receiver);
  }
});

vue双向绑定原理的Object.defineProperty 更改为了 Proxy,性能有所优化

promise *****

解决异步回调地狱问题
var promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});


.then() Promise实例添加状态改变时的回调函数。
.catch() 用于指定发生错误时的回调函数。
Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例。
all中的内容是两个异步操作,只有等到它们的结果都返回了,才会触发pickTopRecommentations这个回调函数。
Promise.race方法同样是将多个Promise实例,包装成一个新的Promise实例。
Promise.resolve()有时需要将现有对象转为Promise对象,Promise.resolve方法就起到这个作用。
Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。
.done()Promise对象的回调链,不管以then方法或catch方法结尾,要是最后一个方法抛出错误,都有可能无法捕捉到
.finally方法用于指定不管Promise对象最后状态如何,都会执行的操作。它与done方法的最大区别,它接受一个普通的回调函数作为参数,该函数不管怎样都必须执行。

Generator 函数的语法 ***

迭代器或解决异步调用回调地狱
function* gen() {
  yield  123 + 456;
}

redux-saga中使用了该语法

async await *****

解决异步回调地域问题,一般和promise一起使用

class 语法糖 ;解决了js中没有类的概念,需要使用 function做为构造函数来使用的问题,简化了继承 *****

class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y); // 调用父类的constructor(x, y)
    this.color = color;
  }

  toString() {
    return this.color + ' ' + super.toString(); // 调用父类的toString()
  }
}

模块module *****

引入模块 import 
输出模块 export 

##28.typescript *
1.基础类型: boolean\number\string\数组\元组(元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同)\枚举(enum类型是对JavaScript标准数据类型的一个补充。 像C#等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字)\ Any\ viod\null\undefined\never(类型表示的是那些永不存在的值的类型)\object
2.变量声明:let const var
3.接口 接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约

interface LabelledValue {  //接口
  label: string;
}

function printLabel(labelledObj: LabelledValue) {
  console.log(labelledObj.label);
}

let myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);

4.类

class Animal {
    move(distanceInMeters: number = 0) {
        console.log(`Animal moved ${distanceInMeters}m.`);
    }
}

class Dog extends Animal {
    bark() {
        console.log('Woof! Woof!');
    }
}

const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();

5.函数

function add(x: number, y: number): number {
    return x + y;
}

let myAdd = function(x: number, y: number): number { return x + y; };

也可以有this和箭头函数

6.泛型可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。

function identity(arg: T): T {
    return arg;
}
let output = identity("myString");  // type of output will be 'string'

7.枚举使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。 TypeScript支持数字的和基于字符串的枚举。

enum Direction {
    Up = 1,
    Down,
    Left,
    Right
}

8.类型推论 这节介绍TypeScript里的类型推论。即,类型是在哪里如何被推断的。
9.类型兼容性
TypeScript里的类型兼容性是基于结构子类型的。 结构类型是一种只使用其成员来描述类型的方式。 它正好与名义(nominal)类型形成对比。
10.高级类型

交叉类型  交叉类型是将多个类型合并为一个类型

联合类型 联合类型表示一个值可以是几种类型之一。
  1. symbol类型的值是通过Symbol构造函数创建的。
let sym1 = Symbol();

let sym2 = Symbol("key"); // 可选的字符串key

12.迭代器和生成器

for..of迭代的是对象的 键 的列表
for..in则迭代对象的键对应的值

13.模块

export 
import

14.命名空间
随着更多验证器的加入,我们需要一种手段来组织代码,以便于在记录它们类型的同时还不用担心与其它对象产生命名冲突。 因此,我们把验证器包裹到一个命名空间内,而不是把它们放在全局命名空间下。
15.声明合并

合并接口
interface Box {
    height: number;
    width: number;
}
interface Box {
    scale: number;
}
let box: Box = {height: 5, width: 6, scale: 10};
合并命名空间
namespace Animals {
    export class Zebra { }
}

namespace Animals {
    export interface Legged { numberOfLegs: number; }
    export class Dog { }
}

  1. jsx语法
  2. 装饰器
    18.mixins

混入 (mixin) 提供了一种非常灵活的方式,
来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
注意: 对于混入的使用,是将 vue的mixin对象重新拷贝到 组件中;降低性能
数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。

是将 vue的mixin对象重新拷贝到 组件中;降低性能 ;vue3.0时会将mixin调优:
Composition API
mixin模式表面上看起来很安全。然而,通过合并对象来共享代码,由于它给代码增加了脆弱性,并且掩盖了推理功能的能力,因此成为一种反模式。
Composition API最聪明的部分是,它允许Vue依靠原生JavaScript中内置的保障措施来共享代码,比如将变量传递给函数和模块系统。
这是否意味着Composition API在各方面都比Vue的经典API优越?不是的。在大多数情况下,你坚持使用经典API是没有问题的。但是,如果你打算重用代码,Composition API无疑是优越的。
链接:https://www.imooc.com/article/303667

19.三斜线指令
20.文件类型检查

##29.队列和栈 *
栈是一种后进先出的数据结构,也就是说最新添加的项最早被移出;它是一种运算受限的线性表,只能在表头/栈顶进行插入和删除操作。
  栈有栈底和栈顶。
  向一个栈插入新元素叫入栈(进栈),就是把新元素放入到栈顶的上面,成为新的栈顶;
  从一个栈删除元素叫出栈,就是把栈顶的元素删除掉,相邻的成为新栈顶;
入栈push 出栈pop

队列是一种先进先出的数据结构。 队列在列表的末端增加项,在首端移除项。
  它允许在表的首端(队列头)进行删除操作,在表的末端(队列尾)进行插入操作;(例如在银行窗口排队办理业务,最前面的第一个人开始办理,后面来的人只能在队伍末尾排队,直到排到他们为止)
  队列是实现多任务的重要机制!
入队列 unshift 出队列 pop

##30. 树组件,遍历树组件 *
https://blog.csdn.net/qq_34295211/article/details/102784498

##31. sass 新特性 **
Sourcemaps
&改善了选择器
改善了if()函数
高级操作列表
新的list-separator()函数
支持Maps
改善了@for循环
@at-root规则
新字符串操作函数
新的@import功能
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
原文: https://www.w3cplus.com/preprocessor/future-sass.html

sass和less区别: *****

  1. sass和less主要区别在于实现方式: less是基于JavaScript的在客户端处理 所以安装的时候用npm,sass是基于ruby所以在服务器处理。
  2. sass与less的安装
    sass基于Ruby语言开发而成,因此安装sass前需要安装Ruby。
    less 在服务器端最容易的安装方式就是通过 npm(node.js 的包管理器)。less 在客户端使用【.less】(LESS源文件),只需要在官网载一个javascript脚本文件主【less.js】,然后在HTML中引入即可。
    3.变量
    sass 是以 开 头 定 义 的 变 量 , 如 : 开头定义的变量,如: mainColor: #963;
    less 是以@开头定义的变量,如 @mainColor: #963;
    4.作用域
    sass 没有全局变量,满足就近原则,但是实际中可以将需要定义的全局属性放在base.scss 文件中。注意变量名重复; less 中的作用域和其他程序语言中的作用域非常的相同,他首先会查找局部定义的变量,如果没有找到,会像冒泡一样,一级一级往下查找,直到根为止。
    区别详细的课参看以下链接:
    https://www.cnblogs.com/tommymarc/p/11627576.html

##32. js排序算法 *
https://www.cnblogs.com/AlbertP/p/10847627.html

##33.网络攻击,及解决办法 *
https://blog.csdn.net/weixin_33781606/article/details/88963588

##34. seo优化 **
1.合理的title、description、keywords
2.语义化的HTML代码,符合W3C规范:语义化代码让搜索引擎容易理解网页
3.非装饰性图片必须加alt
4.友情链接,好的友情链接可以快速的提高你的网站权重
5.外链,高质量的外链,会给你的网站提高源源不断的权重提升
6.向各大搜索引擎登陆入口提交尚未收录站点
7.重要内容HTML代码放在最前:搜索引擎抓取HTML顺序是从上到下,保证重要内容一定会被抓取
8.少用iframe:搜索引擎不会抓取iframe中的内容
9.提高网站速度:网站速度是搜索引擎排序的一个重要指标
##35. 数组去重 ***
https://segmentfault.com/a/1190000016418021

##36. 倒序打印 *
https://blog.csdn.net/qq_42618566/article/details/103187058

##37. css横向居中纵向居中 ****
https://www.cnblogs.com/xiaoxueer/p/11849997.html
https://blog.csdn.net/weixin_37580235/article/details/82317240

38.如何给localStorage设置有效期 **

https://jingyan.baidu.com/article/b2c186c83eef46c46ef6ffbb.html

39.Window. write和document.innerhtml区别 **

主要区别:document.write是直接将内容写入页面的内容流,会导致页面全部重绘,innerHTML将内容写入某个DOM节点,不会导致页面全部重绘
##40.display:none和visibility:hidden的区别是: *
1.display:none是彻底消失,不在文档流中占位,浏览器也不会解析该元素;visibility:hidden是视觉上消失了,可以理解为透明度为0的效果,在文档流中占位,浏览器会解析该元素;
2.使用visibility:hidden比display:none性能上要好,display:none切换显示时visibility,页面产生回流(当页面中的一部分元素需要改变规模尺寸、布局、

相关文章