前端js基础知识(八股文大全)

一、js的数据类型


值类型(基本类型):数字(Number)、字符串(String)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol,大数值类型(BigInt)

引用数据类型:对象(Object)、数组(Array)、函数(Function)、日期(Date)。

注:Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值(标识符)。

基本类型(值类型):

 js基本类型和引用类型区别

      在JavaScript中,基本类型(也称为原始类型)和引用类型(对象类型)的主要区别在于它们的存储方式、赋值行为、比较方式、可变性和传递方式
基本类型(值类型):
    存储方式:存储在栈内存中。
    赋值行为:赋值时创建值的副本。例如,var b = a; b = 20;不会影响a的值。
    比较方式:按值比较,比较的是值是否相等。
    可变性:值一旦创建,不可改变。例如,字符串是不可变的。
    传递方式:作为函数参数时,传递的是值的副本。

1.占用空间固定,保存在栈中,在当前环境执行结束时销毁
2.保存和赋值是值的本身
3.可以使用typeof检测数据类型
4.基本类型数据是值类型


引用类型(对象类型):
    存储方式:存储在堆内存中,栈内存中存储的是对堆内存中对象的引用。
    赋值行为:赋值时复制引用,多个变量可以指向同一个对象。例如,var obj1 = {name: 'A'}; var obj2 = obj1; obj2.name = 'B';此时obj1.name的值也会是'B'。
    比较方式:按引用比较,只有当两个引用指向同一个对象时才认为它们相等。
    可变性:可以修改对象的属性和方法。
    传递方式:作为函数参数时,传递的是引用的副本,但修改参数会直接影响原对象。

1.占用空间不固定,保存在堆中,只有在引用的它的变量不在时,会被垃圾回收机制回收。 (引用变量存储在栈中的是指向堆中的数组或者对象的地址 )
2.保存与复制的是指向对象的一个指针
3.使用instanceof检测数据类型
4.使用new()方法构造出的对象是引用型

   //题二
    var a='哈哈'
    function show(){
        (function(){
            console.log(a) //哈哈
        })()
        console.log(a,'==========') //哈哈
    }
    show()

 //题一
 var a='333'
 function show(){
        (function(){
           console.log(a) //undefined 变量提升
             var a='6'
        })()
       console.log(a,'==========') //33
  }
  show()
 比较运算符的规则

1、数字和数字比较,直接比较大小
2、数字和字符串比较,字符串转换为数字后再比较
3、字符串和字符串比较,进行字符的ASCII码值比较

JS判断数据类型

 JS判断数据类型有typeof、instanceof、通过Object.prototype.toString.call()方法来判断、根据对象的contructor判断。

typeof //其中数组、对象、null都会被判断为object,其他判断都正确

instanceof  //只能正确判断引用数据类型,而不能判断基本数据类型

constructor //constructor有两个作用,一是判断数据的类型, 二是对象实例通过 constrcutor对象访问它的构造函数。需要注意,如果创建一个对象来改变它的原型,constructor就不能用来判断数据类型了;

Object.prototype.toString.call() //可以判断所有类型

typeof

1、基本数据类型中:Number,String,Boolean,undefined 以及引用数据类型中Function ,可以使用typeof检测数据类型,分别返回对应的数据类型的小写字符串
 2、基本数据类型中:null 。引用数据类型中的:Array,Object,Date,RegExp。不可以用typeof检测。都会返回小写的object

console.log(
    typeof 100, //"number"
    typeof 'abc', //"string"
    typeof false, //"boolean"
    typeof undefined, //"undefined"
    typeof null, //"object"
    typeof [1,2,3], //"object"
    typeof {a:1,b:2,c:3}, //"object"
    typeof function(){console.log('aaa');}, //"function"
    typeof new Date(), //"object"
    typeof /^[a-zA-Z]{5,20}$/, //"object"
    typeof new Error() //"object"
    typeof new Number(100), //'object'
    typeof new String('abc'),// 'string'
    typeof new Boolean(true),//'boolean'
);

 instanceof
1.因为A instanceof B 可以判断A是不是B的实例,返回一个布尔值,由构造类型判断出数据类型

2.arr、date、fn分别是数组、日期对象、和函数的实例

console.log(arr instanceof Array ); // true
console.log(date instanceof Date ); // true
console.log(fn instanceof Function ); // true
//注意: instanceof 后面一定要是对象类型,大小写不能写错,该方法试用一些条件选择或分支

 根据对象的contructor判断

arr、date、fn分别是数组、日期对象、和函数的实例

console.log('数据类型判断' -  constructor);
Array.prototype.constructor = Array
console.log(arr.__proto__.constructor === Array); //true
console.log(date.constructor === Date); //true
console.log(fn.constructor === Function); //true

 通过Object.prototype.toString.call()方法来判断

Object.prototype.toString.call();
console.log(toString.call(123)); //[object Number]
console.log(toString.call('123')); //[object String]
console.log(toString.call(undefined)); //[object Undefined]
console.log(toString.call(true)); //[object Boolean]
console.log(toString.call({})); //[object Object]
console.log(toString.call([])); //[object Array]
console.log(toString.call(function(){})); //[object Function]
 判断一个对象为空对象的几种方法

   1、将对象转换成字符串,再判断是否等于“{}”

let obj={};

console.log(JSON.stringify(obj)==="{}");

//返回true

 2、Object.keys()方法,返回对象的属性名组成的一个数组,若长度为0,则为空对象(ES6的写法)

console.log(Object.keys(obj).length==0);//返回true

3、Object.getOwnPropertyNames方法获取对象的属性名,存到数组中,若长度为0,则为空对象

console.log(Object.getOwnPropertyNames(obj).length==0);//返回true

4.for in循环

let result=function(obj){

    for(let key in obj){

        return false;//若不为空,可遍历,返回false

    }

    return true;

}

console.log(result(obj));//返回true

二、数组基本方法

 1.基础方法
push() 从后面添加元素,返回值为添加完后的数组的长度
pop() 从后面删除元素,只能是一个,返回值是删除的元素
shift() 从前面删除元素,只能删除一个 返回值是删除的元素
unshift() 从前面添加元素, 返回值是添加完后的数组的长度
splice(i,n) 删除从i(索引值)开始之后的那个元素。返回值是删除的元素
concat() 连接两个数组 返回值为连接后的新数组
sort() 将数组进行排序,默认根据ASCII码比较,返回值是排好的数组
reverse() 将数组反转,返回值是反转后的数组
slice(start,end) 切去索引值start到索引值end的数组,不包含end索引的值,返回值是切出来的数组
indexOf() 查找某个元素的索引值,若有重复的,则返回第一个查到的索引值若不存在,则返回 -1
Array.isArray() 检测是否是一个数组
join()  默认是以 "," 隔开,返回的是字符串
2.高阶函数
forEach(callback) 遍历数组,无return  即使有return,也不会返回任何值,并且会影响原来的数组
map(callback) 映射数组(遍历数组),有return 返回一个新数组 。

注意:forEach()和map()的区别

1.arr.forEach()是和for循环一样,是代替for。arr.map()是修改数组其中的数据,并返回新的数据。
2.arr.forEach() 没有return arr.map() 有return

filter(callback) 过滤数组,返回一个满足要求的数组 
every(callback) 依据判断条件,数组的元素是否全满足,若满足则返回ture
some() 依据判断条件,数组的元素是否有一个满足,若有一个满足则返回ture
reduce(callback, initialValue) 迭代数组的所有项,累加器,数组中的每个值(从左到右)合并,最终计算为一个值

lastIndexOf() 和arr.indexOf()的功能一样,不同的是从后往前查找
Array.from() 将伪数组变成数组,就是只要有length的就可以转成数组。 —es6
Array.of() 将一组值转换成数组,类似于声明数组 —es6
find(callback) 找到第一个符合条件的数组成员
findIndex(callback) 找到第一个符合条件的数组成员的索引值
fill(target, start, end) 使用给定的值,填充一个数组
includes() 判断数中是否包含给定的值
keys() 遍历数组的键名
values() 遍历数组键值
entries() 遍历数组的键名和键值

三、字符串(String) 

字符串的恒定性:字符串的方法修改字符,不会改变原来的字符串,叫做恒定性

charAt(): 返回指定下标位置的字符。如果index不在0-str.length(不包含str.length)之间,返回空字符串。
charCodeAt(): 返回指定下标位置的字符的unicode编码,这个返回值是 0 - 65535 之间的整数。
indexOf(): 返回某个指定的子字符串在字符串中第一次出现的位置
toLowerCase()把字符串转为小写,返回新的字符串。
toUpperCase(): 把字符串转为大写,返回新的字符串。
lastIndexOf(): 返回某个指定的子字符串在字符串中最后出现的位置。
slice(): 返回字符串中提取的子字符串。 
substring(): 提取字符串中介于两个指定下标之间的字符。	
split(): 把字符串分割成字符串数组。
substr(): 返回从指定下标开始指定长度的的子字符串
replace(): 在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
match(): 返回所有查找的关键字内容的数组。
concat(): 合并

支持正则的四个方法:
	search()
	match()
	split()
	replace()

四、浏览器渲染页面的原理及流程 

浏览器将域名通过网络通信从服务器拿到html文件后,如何渲染页面呢?

1.根据html文件构建DOM树和CSSOM树。构建DOM树期间,如果遇到JS,阻塞DOM树及CSSOM树的构建,优先加载JS文件,加载完毕,再继续构建DOM树及CSSOM树。+
2.构建渲染树(Render Tree)。
3.页面的重绘(repaint)与重排(reflow,也有称回流)。页面渲染完成后,若JS操作了DOM节点,根据JS对DOM操作动作的大小,浏览器对页面进行重绘或是回流

 

五、重绘和回流(repaint&reflow) 

  1、什么是重绘和回流

   当Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流(重排)。

1、页面首次渲染
2、浏览器窗口大小发生改变
3、元素尺寸或位置发生改变
4、元素内容变化(文字数量或图片大小改变而引起的计算值宽度和高度改变)
5、元素字体大小变化
6、添加或者删除可见的DOM元素
7、激活CSS伪类(例如::hover)6
8、查询某些属性或调用某些方法
9、offsetWidth,width,clientWidth,scrollTop/scrollHeight的计算,会使浏览器将渐进回流队列Flush,立即执行回流。

当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘

回流(重排)必定会发生重绘,重绘不一定会引发回流(重排)。

2、如何避免重绘和回流?
   2.1.CSS解决方法

1.避免使用table布局,可能很小的一个小改动会造成整个table的重新布局
2.尽可能在DOM树的最末端改变class。
3.避免设置多层内联样式。
4.将动画效果应用到position属性为absolute或fixed的元素上。
5.动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使用requestAnimationFrame
6.避免使用CSS表达式(例如:calc())
7.使用transform替代top
8.使用visibility替换display: none,因为前者只会引起重绘,后者会引发回流(改变了布局)
将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点

9.使用transform和opacity来实现动画效果

2.2.JS解决方法

1.避免频繁操作样式,最好一次性重写style属性,cssText,或者将样式列表定义为class并一次性更改class属性。
2.避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。
3.也可以先为元素设置display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。
4.避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
5.对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。

6.对于动画等频繁更新的情况,可以使用CSS动画和变换,或者使用requestAnimationFrame。

六、垃圾回收机制(GC)

   JS引擎会在一定的时间间隔来自动对内存进行回收(把内存释放)

  JS垃圾回收机制有两种: 标记清除和引用计数

​ 1.标记清除: js会对变量做一个标记Yes or No的标签以供js引擎来处理, 当变量在某个环境下被使用则标记为yes, 当超出该环境(可以理解为超出作用域)则标记为no, js引擎会在一定时间间隔来进行扫描, 会对所有no标签的变量进行释放(将该变量所占的内存释放掉)

​ 2.引用计数: 对于js中引用类型的变量, 采用引用计数的内存回收机制, 当一个引用类型的变量赋值给另一个变量时, 引用计数会+1, 而当其中有一个变量不再等于值时, 引用计数会-1, 如果引用计数为0, 则js引擎会将其释放掉

 注:JAVA垃圾回收机制方法有:引用计数算法、跟踪回收算法、压缩回收算法、复制回收算法、按代回收算法 

常用垃圾回收算法:标记清除、复制回收、标记整理和分代收集

 七、节流(throttle)与防抖(debounce)

   防抖:任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行

   节流:指定时间间隔内只会执行一次任务。

   注:节流和防抖的共同点,都是减少执行频率,函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数

    触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间

     // 1、防抖功能函数,接受传参
    function debounce(fn,delay==600) {
      // 2、创建一个标记用来存放定时器的返回值
      let timeout = null;
      return function() {
        // 3、每次当用户点击/输入的时候,把前一个定时器清除
        clearTimeout(timeout);
        // 4、然后创建一个新的 setTimeout,
        // 这样就能保证点击按钮后的 interval 间隔内
        // 如果用户还点击了的话,就不会执行 fn 函数
        timeout = setTimeout(() => {
          fn.call(this, arguments);
        }, delay);
      };
    }

 高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率

function throttle(fn,delay=600) {
      // 1、通过闭包保存一个标记
      let canRun = true;
      return function() {
        // 2、在函数开头判断标志是否为 true,不为 true 则中断函数
        if(!canRun) {
          return;
        }
        // 3、将 canRun 设置为 false,防止执行之前再被执行
        canRun = false;
        // 4、定时器
        setTimeout( () => {
          fn.call(this, arguments);
          // 5、执行完事件(比如调用完接口)之后,重新将这个标志设置为 true
          canRun = true;
        }, delay);
      };
    }

 八、for…in 和 for…of的区别

1、推荐在循环对象属性的时候, 使用for…in.
​2、在遍历数组的时候的时候使用for…of。
​3、for…in循环出的是key,for…of循环出的是value

 注意:for…of是ES6新引入的特性。修复了ES5引入的for…in的不足​for…of不能循环普通的对象,需要通过和Object.keys()搭配使用for…of更加强大, 能遍历Array, Map, Set, String,TypedArray,arguments, 而for in 不能遍历map

九、HTTP协议

 1.什么是http协议

 1、超文本传输协议(Hyper Text Transfer Protocol)它是基于TCP协议的应用层传输协议,
简单来说就是客户端和服务端进行数据传输的一种规则

2、http协议常见于 浏览器与服务器的通信,它是属于 应用层 (应用程序)http 默认的端口 80

3、http协议的特点:短连接(断开式) 浏览器向服务器发送请求,服务器接受,并响应
无状态 不知道是谁访问了服务器,

  

1、(cookie+session)
2、token 凭证
cookie基于http协议的一种本地’存储’技术 (它就相当于钱包)
cookie特点
1.基于http协议,解决无状态问题
2.它会随着请求携带到服务器
3.只能存储’字符串’ 4k左右大小
4.能跨域(设置domain),默认不可以
5.容易被伪造,不安全,会造成 xss攻击 (站点伪造)


2 .http 协议一共有五大特点

HTTP 是一个属于应用层的面向对象的协议有五大特点

1.支持客户/服务器模式
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种 方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type(Content-Type是HTTP包中用来表示内容类型的标识)加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开式连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

3.请求和响应报文 

请求报文(request)

1.请求行    [请求方式  url地址  协议(1.0/1.1/2.0) ]
2.请求头    [content-type,cookie]
3.请求体    [数据]

响应报文 (response)

1.状态行  [协议, 状态码,短语]
2.响应头  [content-Type,...Referer:防盗链]
3.响应体  [数据]

 4.什么是ajax

     AJAX (阿贾克斯 Asynchronous Javascript And Xml ) 异步JavaScript和XML,是指一种创建交互式网页应用的网页开发技术, 可以访问服务器数据的局部刷新的技术
  核心对象: XMLHttpRequestajax的异步如何获取到数据

  1、使用onreadystatechange事件(事件队列event loop的宏任务),并结合callback回调函数获取数据

  2、 ajax的同步,发送请求时会占据 (thread main)主线程,造成阻塞,不推荐使用

5.get请求与post请求的区别    

     get和post的请求方式不同

注意:GET产生一个TCP数据包;POST产生两个TCP数据包。Firefox就只发送一次get适合做查询post适合做提交、get只接受ASCII字符,而POST没有限制、get请求比post请求快,post比get请求相对安全、post传输的数据量大,可以传输视频音频等

1、GET在浏览器回退时是无害的,而POST会再次提交请求。
2、GET请求会被浏览器主动cache,而POST不会,除非手动设置。
3、GET请求只能进行url编码,而POST支持多种编码(文字,图片,电影…)方式。
4、GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
5、GET请求在URL中传送的参数是有长度限制的,而POST没有。get做查询post做提交

对参数的数据类型,

6、GET只接受ASCII字符,而POST没有限制。
7、GET比POST更不安全,因为GET的参数直接暴露在URL上,所以不能用来传递敏感信息。
8、GET参数通过URL传递,POST放在Request body中。
9、GET产生的URL地址可以被Bookmark,而POST不可以。
GET请求的速度是POST请求速度的两倍

十、同源策略 

   同源策略是一种浏览器的安全机制,如果出现协议,域名,端口,三者不统一,就会产生跨域

https://www.baidu.com
http://www.baidu.com   //协议不同,跨域

http://www.baidu.com
http://mail.baidu.com    二级域名
http://aaa.bbb.baidu.com 三级域名    域名不同,跨域

http://www.baidu.com:8080
http://www.baidu.com:5500  端口不一致,跨域
 怎么解决跨域(cors)

1、在后端的响应头加上一句 Access-Control-Allow-Origin:*,这里的*表示所有请求,都可以访问该服务

2、采用非官方的跨域方案 ,JSONP, 它算不上真正ajax请求,它只能算get请求,因为它是利用了带src属性的script,不受限制的访问外部资源,再又结合callback回调函数获取数据.

还要和后端配合使用

3、前端使用webpack模块中的server proxy ,实现服务器端代理,来解决跨域

 什么是CORS

1、CORS是一个w3c标准,全称是"跨域资源共享"(Cross-origin resource sharing),它允许浏览器向跨源服务器发送XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

2、CORS需要浏览器和服务器同时支持,整个CORS通信过程,都是浏览器自动完成不需要用户参与,浏览器一旦发现跨域请求,就会添加一些附加的头信息。

注:目前所有最新浏览器都支持该功能,但是万恶的IE不能低于10

浏览器将CORS请求分成两类,简单请求和非简单请求。

    1、简单请求

    凡是同时满足以下两种情况的就是简单请求,反之则非简单请求,浏览器对这两个请求的处理不一样。

  a.请求方法是以下三种方法之一

        HEAD

        GET
       POST
  b.HTTP的头信息不超出以下几种字段:
      Accept
      Accept-Language
      Content-Language
      Last-Event-ID
      Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
  2.非简单请求
非简单请求则是不满足上边的两种情况之一,比如请求的方式为PUT,或者请求头包含其他的字段
非简单请求的CORS请求是会在正式通信之前进行一次预检请求。
浏览器先询问服务器,当前网页所在的域名是否可以请求您的服务器,以及可以使用哪些HTTP动词和头信息。只有得到正确的答复,才会进行正式的请求。

 JSON和JSONP的区别

json是一种轻量级的数据结构,能跨平台进行网络传输,能做配置文件.
jsonp 是一种非官方的跨域解决方案,它是利用script的src,不受限制的访问外部资源,并结合callback拿到数据
它并不是真正的ajax,它是一个get请求,更加适合做查询.
xml   可扩展性标记语言,是一种重量级的数据格式,也能跨平台进行网络传输和配置文件.

十一、new操作符做了什么?

1.在构造函数内部(隐式)创建一个空对象
2.空对象的指针( __ proto __ )指向构造函数的原型(prototype)
3.构造函数的this指向空对象、给空对象添加(自定义的)属性和方法
4.隐式的返回 return this
5、所以new 能改变构造函数内部的this指向,函数内部的this默认是window

        function Perosn(name, age) {
            // 1.在构造函数内部创建一个空对象
            // var obj = new Object();
            //2. obj.__proto__= Perosn.prototype;
            //3.1 Perosn.bind(obj) this指向obj
            //3.2 让空对象拥有 属性和方法 (让this有属性和方法)
            this.name = name; //属性
            this.age = age;   //属性
            this.run = function () { }//方法
            //4.  return this; 是隐式 (看不见的,默认)
            // return this;
        }

        var person = new Perosn("旺旺", 6);
        console.log(person);

 十二、this的理解

   

1、单独使用 this,它指向全局(Global)window对象。

2、在对象方法中, this 指向调用它所在方法的对象。

3、函数使用中,this 指向函数的所属者。

4、严格模式下函数是没有绑定到 this 上,这时候 this 是 undefined。

5、绑定事件this 指向了接收事件的 HTML 元素。apply 和 call 允许切换函数执行的上下文环境(context),即 this 绑定的对象,可以将 this 引用到任何对象。

6、箭头函数中this,沿作用域链向外找,直到有this定义(不受内部定时器影响)

 什么是箭头函数

1、没有this,this指向上下文对象
2、不能被实例化
3、没有构造器
4、如果函数体中只有一句代码 且省略了{} 且你需要返回值 那么必须省略return关键词,如果返回的是对象要用括号括起来

箭头函数为什么没有this指向 

 因js中一开始函数的设计是有缺陷的,因为一个普通函数可以有两种作用域,静态作用域和动态作用域(词法环境)

functon promise() {
    this.PromiseStatus = 'pending'
}
 
let promise = new Promise() //1
promise()             //2

普通函数即可以被用来创建实例(1),又可以被调用执行一段指令序列(2),我们看到一个普通函数也不确定这个函数到底是用来来创建实例还是用来执行一段指令,所以箭头函数设计的初衷就是为了解决函数的二义性(创建实例,执行序列),为了解决这一问题,ES6引入了Class和箭头函数的概念,Class只能用过new关键字来创建实例,而普通函数只能执行一段指令序列,故箭头函数设计的初衷就是不应被创建实例的,因此它内部不存在this指向

十三、堆和栈的区别是什么

 1、内存操作场景

1、栈由操作系统自动分配和释放,用于存放简单的数据段,占据固定大小的空间,比如基本数据类型(Number、String、Boolean……)和函数的参数值等。
2、堆由开发人员自主分配和释放,若不主动释放,程序结束时由浏览器回收,用于存储引用类型(引用类型的变量实际上保存的不是变量本身,而是指向内存空间的指针)。

 
2、数据结构场景

      JavaScript存在栈和队列概念,通过数组的方式,模仿实现堆栈。

栈:栈是一种运算受限的线性表,其限制是指只仅允许在表的一端进行插入和删除操作,这一端被称为栈顶(Top),相对地,把另一端称为栈底(Bottom)。把新元素放到栈顶元素的上面,使之成为新的栈顶元素称作进栈、入栈或压栈(Push);把栈顶元素删除,使其相邻的元素成为新的栈顶元素称作出栈或退栈(Pop)。通过数组的push()、pop()方法实现栈。
堆:堆其实是一种优先队列,也就是说队列中存在优先级,比如队列中有很多待执行任务,执行时会根据优先级找优先度最高的先执行。

 十四、进程与线程的区别

1、线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;
2、一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线

3、进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信号等),某进程内的线程在其他进程不可见;
 4、调度和切换:线程上下文切换比进程上下文切换要快得多

 十五、cookie 、sessionStorage与localStorage的区别

特性cookiesessionStoragelocalStorage
数据的生命期一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效仅在当前会话下有效,关闭页面或浏览器后被清除除非被清除,否则永久保存
存放数据大小4K左右一般为5MB一般为5MB
与服务器端通信每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题仅在客户端(即浏览器)中保存,不参与和服务器的通信仅在客户端(即浏览器)中保存,不参与和服务器的通信
易用性需要程序员自己封装,源生的Cookie接口不友好源生接口可以接受,亦可再次封装来对Object和Array有更好的支持源生接口可以接受,亦可再次封装来对Object和Array有更好的支持
提供方法需自己编写或引用第三方库1).setItem (key, value) —— 保存数据,以键值对的方式储存信息。
2).getItem (key) —— 获取数据,将键值传入,即可获取到对应的value值。
3).removeItem (key) —— 删除单个数据,根据键值移除对应的信息。
4).clear () —— 删除所有的数据
5).key (index) —— 获取某个索引的key
1).setItem (key, value) —— 保存数据,以键值对的方式储存信息。
2).getItem (key) —— 获取数据,将键值传入,即可获取到对应的value值。
3).removeItem (key) —— 删除单个数据,根据键值移除对应的信息。
4).clear () —— 删除所有的数据
5).key (index) —— 获取某个索引的key

cookie、localstorage和sessionStorage三者都是临时存储客户端会话信息或数据的方法,下面就简单介绍一下三者的区别:

存储的时间有效期不同
1、cookie的有效期是可以设置的,默认的情况下是关闭浏览器后失效
2、sessionStorage的有效期是仅保持在当前页面,关闭当前会话页或者浏览器后就会失效
3、localStorage的有效期是在不进行手动删除的情况下是一直有效的
存储的大小不同
1、cookie的存储是4kb左右,存储量较小,一般页面最多存储20条左右信息
2、localStorage和sessionStorage的存储容量是5Mb(官方介绍,可能和浏览器有部分差异性)
与服务端的通信
1、cookie会参与到与服务端的通信中,一般会携带在http请求的头部中,例如一些关键密匙验证等。
2、localStorage和sessionStorage是单纯的前端存储,不参与与服务端的通信

十六、前端性能优化

   1、defer和async的区别

    defer:在HTML解析完之后才会执行。如果是多个,则按照加载的顺序依次执行。
    async:在加载完之后立即执行。如果是多个,执行顺序和加载顺序无关

 <script src="./async1.js" async defer></script>
   2、 减少 HTTP 请求数量

        基本原理:在浏览器与服务器进行通信时,主要是通过 HTTP 进行通信。浏览器与服务器需要经过三次握手,每次握手需要花费大量时间。而且不同浏览器对资源文件并发请求数量有限(不同浏览器允许并发数),一旦 HTTP 请求数量达到一定数量,资源请求就存在等待状态,这是很致命的,因此减少 HTTP 的请求数量可以很大程度上对网站性能进行优化。
            CSS Sprites:国内俗称 CSS 精灵,这是将多张图片合并成一张图片达到减少 HTTP 请求的一种解决方案,可以通过 CSS background 属性来访问图片内容。这种方案同时还可以减少图片总字节数,节省命名词汇量(由命名多张图片文件变成一张,哈哈哈)。
            合并 CSS 和 JS 文件:现在前端有很多工程化打包工具,如:grunt、gulp、webpack等。为了减少 HTTP 请求数量,可以通过这些工具再发布前将多个 CSS 或者 多个 JS 合并成一个文件。
            采用 lazyLoad:俗称懒加载,可以控制网页上的内容在一开始无需加载,不需要发请求,等到用户操作真正需要的时候立即加载出内容。这样就控制了网页资源一次性请求数量。

   3、控制资源文件加载优先级

        基本原理:说到这里就需要知道浏览器加载 HTML 内容的原理,浏览器在加载 HTML 内容时,是将 HTML 内容从上至下依次解析,解析到 link 或者 script 标签就会加载 href 或者 src 对应链接内容,为了第一时间展示页面给用户,就需要将 CSS 提前加载,不要受 JS 加载影响。
            遵循原则:主要文件放在 head 内部,次要文件放在 body 底部。一般情况下都是 CSS 在头部,JS 在底部。

    4、利用浏览器缓存    

基本原理:浏览器缓存分强缓存和协商缓存,他们是将网络资源存储在本地,等待下次请求该资源时,如果命中就不需要到服务器重新请求该资源,直接在本地读取该资源。
 强缓存:在 web 服务器返回的响应中添加 Expires 和 Cache-Control Header。
 协商缓存:通过【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】这两对 Header 分别管理。

  5、 使用 CDN
        基本原理:CDN的全称是Content Delivery Network,即内容分发网络。

    减少重排(Reflow)
    基本原理:重排是 DOM 的变化影响到了元素的几何属性(宽和高),浏览器会重新计算元素的几何属性,会使渲染树中受到影响的部分失效,浏览器会验证 DOM 树上的所有其它结点的 visibility 属性,这也是 Reflow 低效的原因。如果 Reflow 的过于频繁,CPU 使用率就会急剧上升。
    减少 Reflow,如果需要在 DOM 操作时添加样式,尽量使用 增加 class 属性,而不是通过 style 操作样式。

    6、减少 DOM 操作

    使用createDocumentFragment

    7、图标使用 IconFont 替换

十七、网络安全

1、什么是xss攻击

**跨站脚本攻击。**XSS的重点不在于跨站点,而在于脚本的执行
恶意攻击者在web页面中会插入一些恶意的script代码。当用户浏览该页面的时候,那么嵌入到web页面中script代码会执行,因此会达到恶意攻击用户的目的


如何防范?

1、请求方式:尽量采用POST而非GET提交表单
2、输入验证和过滤:对用户输入进行验证和过滤,确保只允许合法的数据输入。
3、输出转义“在输出用户输入到页面时,使用适当的转义函数将特殊字符转义为 HTML 实体,防止脚本被执行
4、HTTP 头部设置:使用 Content Security Policy(CSP)等 HTTP 头部设置,限制浏览器执行外部脚本的能力。
5、使用安全框架:使用安全框架,例如 Laravel、Django 等,它们通常提供了自动的输入验证和输出转义机制。
6、定期安全审计:定期进行安全审计,检查应用程序中是否存在潜在的 XSS 漏洞,及时修复已知漏洞

7、后端需要对提交的数据进行过滤

十八、什么是oop(面向对象) 

   oop(面向对象)是一种编程思想,又叫做面向对象编程(ooa面向对象分析,ood面向对象设计)
它有三大特性封装、继承、多态。

1、这种编程方式,更加贴近现实;
2、java,c#, c++ , js … 面向对象编程,是主流;

封装:将相同的属性和方法提取成一个类
继承:子类拥有父类的属性和方法
多态:重写子类重写父类的属性和方法
重载:在同一个类中,同名不同参数 js没有重载

   同一个类中,同名不同参数 (在同一个类中,函数名称相同,参数的个数和类型不相同)
   注意: js没有重载

面向对像继承

1. 对象冒充继承  使用 bind,call,apply 解决构造函数属性的继承
缺点:不能继承原型上的属性和方法
2. 原型链继承   
缺点:不能让构造函数的属性,初始化
3. 组合继承 (对象冒充+原型继承)
缺点:原型中会有多余的属性,并且是undefined
4. ES6的class和extends继承
5. 寄生组合继承  Object.create(base.prototype);

什么是面向过程?与面向对象有什么区别?

面向过程:

就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,
使用的时候一个一个依次调用就可以了。

面向对象:

是把构成问题的事务分解成各个对象,每个对象都有自己独立的属性和行为,
对象可以将整个问题事务进行分工, 不同的对象做不同的事情,
这种面向对象的编程思想由于更加贴近实际生活, 所以被计算机语言广泛应用。

js有2种编程模式:面对过程、面向对象

 递归

1、函数自己调用自己,要有零界点(结束条件)
2、循环的能做的事,递归都能实现

递归的使用场景
  1. 快速排序使用递归
  2. nodejs磁盘文件的遍历,使用递归
  3. 管理系统的权限菜单栏(n级菜单栏)
  4. 对象的深拷贝

类和对象的关系

类是对象的抽象,而对象是类的具体实例。
类是抽象的,不占用内存,而对象是具体的,占用存储空间。
类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。
类与对象的关系就如模具和铸件的关系
类的实例化结果就是对象,而对一类对象的抽象就是类,
类描述了一组有相同属性和相同方法的对象

 十九、原型

  1.什么是原型?

原型, 英文名prototype是函数中一个自带的属性,用来添加公共属性的方法,我们创建的每个函数都有一个
prototype(原型)属性,这个属性是一个对象.
~

2.原型的作用?

原型的作用是: 可以让同一个构造函数创建的所有对象共享属性和方法. 也就是说, 你可以不在
构造函数中定义对象的属性和方法,
而是可以直接将这些信息添加到原型对象中。 

3.原型的好处?

 优点:
1, 实例对象都有自己的独有属性
2, 同时共享了原型中的方法,最大限度的节省了内存
3, 支持向构造函数传递参数 (初始值)

 4.什么是原型链?

当访问一个实列对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找的过程就会形成一个链式结构,我们-称为原型链

二十、Promise

回调函数是用来解决异步或对函数进行功能扩展,如果滥用回调函数的嵌套,就会形成回调地狱
回调地狱,不方便维护与代码的理解,就可以采用Promise.(不仅能解决回调地狱还能做并发)
promsie是一个类,需要被实例化,微任务

promsie 有三种状态
1.pending 等待 默认是 等待
2.fulfilled 完成
3.rejected  拒绝
它们顺序是不可以逆的
promsie的原型方法

then() 里面有2个函数,第1个函数取resolve的结果,第2个参数取reject的结果
catch() 捕获 reject的结果
finally() 只要执行resolve或reject后,都会执行finally

promise的静态方法

Promise.all() ,all方法里需要填入一个数组,数组里必须都是支持promise的方法,迸发执行

Promise.race(),race方法里需要填入一个数组,谁先完成,就只取谁的结果

Promise.resolve() 只执成功,并返回一个新的promise对象

Promise.reject() 只执失败,并返回一个新的promise对象

ES7 async await

await关键字后面必须接promise对象,有await关键字的地方,必须是一个async 异步函数

二十一、什么是闭包(Closure)

  闭包是这样一种机制:函数嵌套函数,内部函数可以引用外部函数的参数和变量,参数和变量不会被垃圾回收机制所收回。

闭包的好处

1、可以让一个变量长期驻扎在内存当中不被释放,在IE6、7、8下会存在内存溢出
2、避免全局变量的污染, 和全局变量不同, 闭包中的变量无法被外部使用

闭包的用途 

1.实现缓存

2.存储值与避免变量全局污染

3.函数的柯里化

4.节流和防抖

 使用闭包的注意点

1、由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。
2、闭包会在父函数外部,改变父函数内部变量的值。 

二十二、JavaScript的事件循环机制

  JavaScript语言最大的特点就是单线程,即同一时间只能做一件事情,做完一件事情之后才能去做另一件事情。单线程就意味着所有任务需要排队,前一个任务结束才会执行后一个任务。

同步任务(synchronous):

      同步任务指的是:在主线程上排队执行的任务,只有前一个任务执行完毕才能执行后一个任务。所有的同步任务都在主线程上执行,形成了一个执行栈。执行栈的执行顺序是后进先出。       

异步任务(asynchronous):

     异步任务指的是:不进入主线程,而是进入“任务队列”的任务。只有“任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

事件循环过程:

同步任务和异步任务分别进行不同的场所,同步任务进入主线程,异步任务进入事件表(Event Table)并且注册函数。当指定的事情完成之后(例如接受到了Promise对象的返回结果resolve/reject),事件表(Event Table)会将这个函数移入到任务队列(Event Queue)。主线程内的任务执行完毕之后,回去任务队列(Event Queue)读取对应的函数移入到主线程执行

上述过程不断重复,这就是事件循环(Event Loop)

宏任务和微任务

宏任务(macro-task)包含:整体代码script、setTimeout函数、setInterval函数。

微任务(micro-task)包含:Promise、process.nextTick。

事件循环的顺序决定了JavaScript代码的执行顺序。首先进入整体代码script对应的脚本文件之后,开始第一次的循环。

接着执行所有的微任务,然后再次从宏任务开始执行,找到对应的任务队列执行完毕,再次执行所有的微任务,以此循环。

在执行宏任务或者微任务的过程中,里面的微任务的优先级是大于宏任务的,也就是先执行微任务再执行宏任务。

分析一下代码段的执行过程,并写出输出结果:

	setTimeout(()=>{
		console.log("定时器")
	})
	new Promise(funtion(resolve,reject){
		console.log("Promise")
		resolve()
	}).then(res=>{
		console.log("回调")
	})
	console.log("结束")
任务执行过程

1、首先进入整个js文件,是一个宏任务。

2、遇到setTimeout宏任务,这是一个异步任务,进入事件表(Event Table)并注册函数,等定时结束之后将函数移入到任务队列(Event Queue)

3、遇到 new Promise执行同步代码console.log("Promise"),输出Promise。接收到resolve的返回结果,遇到then回调微任务,进入事件表(Event Table)并注册函数,然后将这个函数移入到任务队列(Event Queue)

4、遇到console.log("结束")。输出结束

5、一轮宏任务处理完毕,判断是否有微任务需要处理。有then回调微任务,输出Promise回调

6、一轮事件循环结束,先找到setTimeout宏任务执行,输出定时器,再继续寻找是否有微任务?没有,开始下一轮事件循环。是否有宏任务可以进行循环?没有,事件循环结束。

  • 24
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue.js前端面试八股文涵盖了多个方面的知识点。其中包括了CSS、JavaScript、Vue、Webpack、Vite、HTML5新特性等等。在面试中,可能会涉及到一些常见的主题,例如BFC、V8垃圾回收机制、Vite和Webpack的区别、Vue中常见的问题、防抖节流、深拷贝、浅拷贝、盒子模型、作用域、闭包、浏览器等。这些都是前端开发中常见的知识点,掌握它们可以帮助你在面试中更好地回答问题。同时,前后端职责分离也是一个重要的概念,前端负责交互逻辑,后端负责数据处理。然而,Vue.js前端面试八股文不仅仅限于这些内容,还可能包括其他相关的知识点。因此,在准备面试时,建议你全面了解Vue.js和相关技术的知识,以便能够更好地回答面试官的问题。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [2023年前端面试必备最新八股文(基础+进阶内容+持续更新)](https://download.csdn.net/download/qq_38951259/87507329)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [VUE 前端 面试 技术 八股文](https://download.csdn.net/download/qq_39258956/88011311)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dogface07

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值