1 JavaSctipt前端面试小记(WW)

目录

1 JavaSpritp 深浅拷贝

2 Vue 3的响应式原理

3 手写 new

4 从输⼊URL到⻚⾯加载完中间发⽣了什么?

5 JavaScript脚本延迟加载的方式有哪些?

6 http https 网络基础八股文

7 什么是DOM和BOM?

 8 escape、encodeURI、encodeURIComponent的区别

9 对AJAX的理解,实现一个AJAX请求

10 什么是尾调用,使用尾调用有什么好处?

JavaScript Event Loop

 12 说一下vue 中的diff算法 

13 什么是闭包 ?

14 js垃圾回收机制

15 HTTPS协议对称加密的过程? 

16  React组件间传值的方法有哪些?

17 XSS攻击是什么?

18 请你说说事件扩展符用过吗(...),什么场景下

19 ES6模块与CommonJS模块有什么异同?

20 for...in和for...of的区别

21 对原型、原型链的理解

22对作用域、作用域链的理解

23 对this对象的理解

24 call()和apply()的区别?

25 异步编程的实现方式?

26 对Promise的理解

27Promise解决了什么问题

28 对async/await的理解

30 async/await的优势

31 async/await对比Promise的优势

32  对象创建的方式有哪些

33 对象继承的方式有哪些?

 34  哪些情况会导致内存泄漏


1 JavaSpritp 深浅拷贝

详细讲解js中的深拷贝与浅拷贝_静茹秋叶的博客-CSDN博客_js浅拷贝和深拷贝


2 Vue 3的响应式原理

VUE3的响应式原理_阿正ºº⁷的博客-CSDN博客_vue3响应式原理

手撕 Posxy


3 手写 new

function myNew(fn,...args){
    if(typeof fn != 'function'){
        console.error('ErrorType')
        return
    }
    let newObj = Object.create(fn.prototype)
    let result = fn.apply(newObj,args)
    return result && (typeof result == 'function'|| typeof result == 'object') ? resulet : newObj
}

4 从输⼊URL到⻚⾯加载完中间发⽣了什么?

说说从输入URL到看到页面发生的全过程_LuckXinXin的博客-CSDN博客

1 首先浏览器主进程接管,开了一个下载线程。
2 然后进行HTTP请求(DNS查询、IP寻址等等),中间会有三次捂手,等待响应,开始下载响应报文。
3 将下载完的内容转交给Renderer进程管理。
4 Renderer进程开始解析css rule tree和dom tree,这两个过程是并行的,所以一般我会把link标签放在页面顶部。
5 解析绘制过程中,当浏览器遇到link标签或者script、img等标签,浏览器会去下载这些内容,遇到时候缓存的使用缓存,不适用缓存的重新下载资源。
6 css rule tree和dom tree生成完了之后,开始合成render tree,这个时候浏览器会进行layout,开始计算每一个节点的位置,然后进行绘制。
7 绘制结束后,关闭TCP连接,过程有四次挥手
 

5 JavaScript脚本延迟加载的方式有哪些?

对于js的优化(关于js的延迟加载)的好处是有助于提高页面加载速度,js延迟加载就是等页面加载完成之后在加载js文件.

JS为什么要延迟加载,有哪些方法可以实现延迟加载?_燕穗子博客的博客-CSDN博客_前端延迟加载

6 http https 网络基础八股文

测试秋招八股文集锦——经典网络篇_笔经面经_牛客网一、前言:激动的心颤抖的手 测试秋招八股文集锦之信心鼓励篇发出3天时间内,被收藏124次,浏览1.8***丝也由178涨到了237,更激动的是俺红名啦!!!有点受宠若惊。 信心鼓励篇不知道有没有https://www.nowcoder.com/discuss/1020313?type=2&channel=-1&source_id=discuss_terminal_discuss_hot_nctrack

7 什么是DOM和BOM?

27、什么是DOM和BOM_C.&H.的博客-CSDN博客_dom和bom含义分别是什么

 8 escape、encodeURI、encodeURIComponent的区别

简单明了区分escape、encodeURI和encodeURIComponent_weixin_30868855的博客-CSDN博客

9 对AJAX的理解,实现一个AJAX请求

对Ajax的简单理解与使用_菜鸟yl的博客-CSDN博客

ajax的优缺点:

优点:

1.在不刷新页面的情况下与服务器通信;

2.使用异步的方式与服务器通信,不打断用户的操作;

3.无需重新加载整个网页,只需要与服务器进行少量的数据交换,就能够实现对网页中的某一部分进行更新,从而减少了带宽的占用。

4、AJAX是在客户端运行的,它承载了一部分本来由服务器承担的工作,减少了大用户量下的服务器负载。

5.基于标准化而被广泛支持的技术,不需要下载插件或者是小程序。

缺点:

1.ajax不支持浏览器的回退按钮;

2.ajax暴露了与服务器交互的细节;

3.ajax对搜素引擎的支持比较弱;

4.不容易调试。

10 什么是尾调用,使用尾调用有什么好处?

尾调用指的是函数的最后一步调用另一个函数。代码执行是基于执行栈的,所以当在一个函数里调用另一个函数时,会保留当前的执行上下文,然后再新建另外一个执行上下文加入栈中。使用尾调用的话,因为已经是函数的最后一步,所以这时可以不必再保留当前的执行上下文,从而节省了内存,这就是尾调用优化。但是ES6的尾调用优化只在严格模式下开启,正常模式是无效的。

JS进阶 - 什么是 尾调用、尾递归、蹦床函数_Jioho_的博客-CSDN博客_蹦床函数

 ES6的尾调用

缩减严格模式里尾调用栈帧的大小,如果满足以下条件,不再创建新栈帧,而是清空并重用当前函数的栈帧:

  1. 尾调用不再访问当前栈帧的变量(函数不是闭包)
  • 尾调用必须是最后一条语句
  • 尾调用必须作为结果返回

JavaScript Event Loop

调用栈> 微任务队列 > 消息队列 

 

 12 说一下vue 中的diff算法 

详解vue的diff算法 - _wind - 博客园

13 什么是闭包 ?

简单理解js闭包的概念,值得受益!_云澈丿的博客-CSDN博客_js中闭包

14 js垃圾回收机制

面试题——js垃圾回收机制和引起内存泄漏的操作_yingzizizizizizzz的博客-CSDN博客_js垃圾回收机制面试题JS的垃圾回收机制了解吗?       Js具有自动垃圾回收机制。垃圾收集器会按照固定的时间间隔周期性的执行。JS中最常见的垃圾回收方式是标记清除。工作原理:是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。工作流程:1.    垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记。2.https://blog.csdn.net/yingzizizizizizzz/article/details/77333996?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166102281116782390528343%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166102281116782390528343&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-77333996-null-null.142%5Ev42%5Epc_rank_34,185%5Ev2%5Econtrol&utm_term=js%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%E9%9D%A2%E8%AF%95%E9%A2%98&spm=1018.2226.3001.4187

面试题——js之垃圾回收、 内存泄漏_Hell's Angel的博客-CSDN博客

15 HTTPS协议对称加密的过程? 

client请求服务端(指定SSL版本和加密组件)
server返回CA证书+公钥
client用机构公钥认证server返回的CA证书上的签名是否正确
client生成一个密钥R,用公钥对密钥R加密发送给server server用服务器的私钥解密获取密钥R
后续通信都是采用密钥R进行加密

16  React组件间传值的方法有哪些?

⽗组件向⼦组件传值(通过props传值)
⽗组件向⼦组件传值(回调函数)
兄弟组件传值(⼦传给⽗,⽗再传给另⼀个⼦)

17 XSS攻击是什么?

跨站脚本攻击

18 请你说说事件扩展符用过吗(...),什么场景下

合并数组

与解构赋值结合

函数的返回值

字符串

实现了 Iterator 接口的对象

Map 和 Set

19 ES6模块与CommonJS模块有什么异同?

ES6Module和CommonJS模块的区别:CommonJS是对模块的浅拷⻉,ES6Module是对模块的引用,即ES6Module只存只读,不能改变其值,也就是指针指向不能变,类似const;import的接口是read-only(只读状态),不能修改其变量值。即不能修改其变量的指针指向,但可以改变变量内部指针指向,可以对commonJS对重新赋值(改变指针指向),但是对ES6Module赋值会编译报错。

ES6Module和CommonJS模块的共同点:CommonJS和ES6Module都可以对引入的对象进行赋值,即对对象内部属性的值进行改变。

因为CommonJS的require语法是同步的,导致CommonJS只适合用于服务端;而ES6模块在浏览器端和服务器端都是可用的,但是在服务端需要遵循特殊的规则
CommonJS模块输出的是一个值的拷贝,而ES6模块输出的是值的引用
CommonJS模块是运行时加载;ES6模块是编译时输出的接口,方便对JS模块进行静态分析
关于互相引用问题,ES6模块中支持加载CommonJS;而CommonJS不支持引用ES6模块
 

20 for...in和for...of的区别

for...of是ES6新增的遍历方式,允许遍历一个含有iterator接口的数据结构(数组、对象等)并且返回各项的值,

和ES3中的for...in的区别如下for...of遍历获取的是对象的键值,for...in获取的是对象的键名;

for...in会遍历对象的整个原型链,性能非常差不推荐使用,而for...of只遍历当前对象不会遍历原型链;对于数组的遍历,for...in会返回数组中所有可枚举的属性(包括原型链上可枚举的属性),for...of只返回数组的下标对应的属性值;

总结:for...in循环主要是为了遍历对象而生,不适用于遍历数组;for...of循环可以用来遍历数组、类数组对象,字符串、Set、Map以及Generator对象。

21 对原型、原型链的理解

JS系列——js原型链_过往深处少年蓝的博客-CSDN博客_js原型链

22对作用域、作用域链的理解

(1)全局作用域

最外层函数和最外层函数外面定义的变量拥有全局作用域
所有未定义直接赋值的变量自动声明为全局作用域
所有window对象的属性拥有全局作用域
全局作用域有很大的弊端,过多的全局作用域变量会污染全局命名空间,容易引起命名冲突。
(2)函数作用域
函数作用域声明在函数内部的变零,一般只有固定的代码片段可以访问到
作用域是分层的,内层作用域可以访问外层作用域,反之不行
块级作用域
使用ES6中新增的let和const指令可以声明块级作用域,块级作用域可以在函数中创建也可以在一个代码块中的创建(由{ }包裹的代码片段)
let和const声明的变量不会有变量提升,也不可以重复声明
在循环中比较适合绑定块级作用域,这样就可以把声明的计数器变量限制在循环内部。
 

作用域链的作用是保证对执行环境有权访问的所有变量和函数的有序访问,通过作用域链,可以访问到外层环境的变量和函数。

作用域链的本质上是一个指向变量对象的指针列表。变量对象是一个包含了执行环境中所有变量和函数的对象。作用域链的前端始终都是当前执行上下文的变量对象。全局执行上下文的变量对象(也就是全局对象)始终是作用域链的最后一个对象。当查找一个变量时,如果当前执行环境中没有找到,可以沿着作用域链向后查找。

23 对this对象的理解

this是执行上下文中的一个属性,它指向最后一次调用这个方法的对象。在实际开发中,this的指向可以通过四种调用模式来判断。

第一种是函数调用模式,当一个函数不是一个对象的属性时,直接作为函数来调用时,this指向全局对象。

第二种是方法调用模式,如果一个函数作为一个对象的方法来调用时,this指向这个对象。

第三种是构造器调用模式,如果一个函数用new调用时,函数执行前会新创建一个对象,this指向这个新创建的对象。

第四种 忘记

第四种是apply、call和bind调用模式,这三个方法都可以显示的指定调用函数的this指向。其中apply方法接收两个参数:一个是this绑定的对象,一个是参数数组。call方法接收的参数,第一个是this绑定的对象,后面的其余参数是传入函数执行的参数。也就是说,在使用call()方法时,传递给函数的参数必须逐个列举出来。bind方法通过传入一个对象,返回一个this绑定了传入对象的新函数。这个函数的this指向除了使用new时会被改变,其他情况下都不会改变。

这四种方式,使用构造器调用模式的优先级最高,然后是apply、call和bind调用模式,然后是方法调用模式,然后是函数调用模式。

24 call()和apply()的区别?

它们的作用一模一样,区别仅在于传入参数的形式的不同。apply接受两个参数,第一个参数指定了函数体内this对象的指向,第二个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组,apply方法把这个集合中的元素作为参数传递给被调用的函数。call传入的参数数量不固定,跟apply相同的是,第一个参数也是代表函数体内的this指向,从第二个参数开始往后,每个参数被依次传入函数。

25 异步编程的实现方式?

JavaScript中的异步机制可以分为以下几种:

回调函数的方式,使用回调函数的方式有一个缺点是,多个回调函数嵌套的时候会造成回调函数地狱,上下两层的回调函数间的代码耦合度太高,不利于代码的可维护。

Promise的方式,使用Promise的方式可以将嵌套的回调函数作为链式调用。但是使用这种方法,有时会造成多个then的链式调用,可能会造成代码的语义不够明确。

generator的方式,它可以在函数的执行过程中,将函数的执行权转移出去,在函数外部还可以将执行权转移回来。当遇到异步函数执行的时候,将函数执行权转移出去,当异步函数执行完毕时再将执行权给转移回来。因此在generator内部对于异步操作的方式,可以以同步的顺序来书写。

使用这种方式需要考虑的问题是何时将函数的控制权转移回来,因此需要有一个自动执行generator的机制,比如说co模块等方式来实现generator的自动执行。

async函数的方式,async函数是generator和promise实现的一个自动执行的语法糖,它内部自带执行器,当函数内部执行到一个await语句的时候,如果语句返回一个promise对象,那么函数将会等待promise对象的状态变为resolve后再继续向下执行。因此可以将异步逻辑,转化为同步的顺序来书写,并且这个函数可以自动执行。

26 对Promise的理解

promise是一个对异步操作进行封装并返回其结果的构造函数.
使代码更加简洁和避免回调地狱。

Promise是异步编程的一种解决方案,它是一个对象,可以获取异步操作的消息,他的出现大大改善了异步编程的困境,避免了地狱回调,它比传统的解决方案回调函数和事件更合理和更强大。

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。Promise提供统一的API,各种异步操作都可以用同样的方法进行处理。

(2)Promise的实例有两个过程:pending->fulfilled:Resolved(已完成)pending->rejected:Rejected(已拒绝)注意:一旦从进行状态变成为其他状态就永远不能更改状态了。Promise的特点:对象的状态不受外界影响。promise对象代表一个异步操作,有三种状态,pending(进行中)、fulfilled(已成功)、rejected(已失败)。

只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,这也是promise这个名字的由来——“承诺”;

注意:在构造Promise的时候,构造函数内部的代码是立即执行的

27Promise解决了什么问题

后一个请求需要依赖于前一个请求成功后,将数据往下传递,会导致多个ajax请求嵌套的情况,代码不够直观。

如果前后两个请求不需要传递参数的情况下,那么后一个请求也需要前一个请求成功后再执行下一步操作,这种情况下,那么也需要如上编写代码,导致代码不够直观。Promise出现之后,代码变成这样:这样代码看起了就简洁了很多,解决了地狱回调的问题。

28 对async/await的理解

async/await其实是Generator的语法糖,它能实现的效果都能用then链来实现,它是为优化then链而开发出来的。从字面上来看,async是“异步”的简写,await则为等待,所以很好理解async用于申明一个function是异步的,而await用于等待一个异步方法执行完成

async函数返回的是一个Promise对象。

如果在函数中return一个直接量,async会把这个直接量通过Promise.resolve()封装成Promise对象

then()链来处理这个Promise对象

如果async函数没有返回值

它会返回Promise.resolve(undefined)

30 async/await的优势

单一的Promise链并不能发现async/await的优势,但是,如果需要处理由多个Promise组成的then链的时候,优势就能体现出来了

结果和之前的Promise实现是一样的,但是这个代码看起来是不是清晰得多,几乎跟同步代码一样

31 async/await对比Promise的优势

1 代码读起来更加同步,Promise虽然摆脱了回调地狱,但是then的链式调用也会带来额外的阅读负担

2 Promise传递中间值非常麻烦,而async/await几乎是同步的写法,

3 非常优雅错误处理友好,async/await可以用成熟的try/catch,

4 Promise的错误捕获非常冗余调试友好,

Promise的调试很差,由于没有代码块,你不能在一个返回表达式的箭头函数中设置断点,如果你在一个.then代码块中使用调试器的步进(step-over)功能,调试器并不会进入后续的.then代码块,因为调试器只能跟踪同步代码的每一步。

32  对象创建的方式有哪些

1、{}
2、new Object()
3、使用字面量

对象字面变量是对象定义的一种简写形式,举个例子:
var person = {name: 'zhang', age:20}, 这就是字面量形式,完全等价于var person = {}; person.name='zhang'; person.age=20;

小结:前面三种创建对象的方式存在2个问题:1.代码冗余; 2.对象中的方法不能共享,每个对象中的方法都是独立的。
 


4、工厂模式
5、构造函数模式(constructor)

所谓构造函数,也是普通的函数,不过约定俗成,构造函数的名称首字母大写,普通函数的首字母小写。通过new 构造函数来创建对象
6、原型模式(prototype)

每个方法中都有一个原型(prototype),每个原型都有一个构造器(constructor),构造器又指向这个方法。



        /*
         *  原型模式创建对象
         */
        function Animal() { }

        Animal.prototype.name = 'animal';
        Animal.prototype.sayName = function () { alert(this.name); };

        var a1 = new Animal();
        var a2 = new Animal();

        a1.sayName();

        alert(a1.sayName === a2.sayName);//true
        alert(Animal.prototype.constructor);//function Animal(){}
        alert(Animal.prototype.constructor==Animal);//true

通过原型创建对象,把属性和方法绑定到prototype上,通过这种方式创建对象,方法是共享的,每个对象调用的是同一个方法。

33 对象继承的方式有哪些?

(1)第一种是以原型链的方式来实现继承,但是这种实现方式存在的缺点是,在包含有引用类型的数据时,会被所有的实例对象所共享,容易造成修改的混乱。还有就是在创建子类型的时候不能向超类型传递参数。

(2)第二种方式是使用借用构造函数的方式,这种方式是通过在子类型的函数中调用超类型的构造函数来实现的,这一种方法解决了不能向超类型传递参数的缺点,但是它存在的一个问题就是无法实现函数方法的复用,并且超类型原型定义的方法子类型也没有办法访问到。

(3)第三种方式是组合继承,组合继承是将原型链和借用构造函数组合起来使用的一种方式。通过借用构造函数的方式来实现类型的属性的继承,通过将子类型的原型设置为超类型的实例来实现方法的继承。这种方式解决了上面的两种模式单独使用时的问题,但是由于我们是以超类型的实例来作为子类型的原型,所以调用了两次超类的构造函数,造成了子类型的原型中多了很多不必要的属性。

(4)第四种方式是原型式继承,原型式继承的主要思路就是基于已有的对象来创建新的对象,实现的原理是,向函数中传入一个对象,然后返回一个以这个对象为原型的对象。这种继承的思路主要不是为了实现创造一种新的类型,只是对某个对象实现一种简单继承,ES5中定义的Object.create()方法就是原型式继承的实现。缺点与原型链方式相同。

(5)第五种方式是寄生式继承,寄生式继承的思路是创建一个用于封装继承过程的函数,通过传入一个对象,然后复制一个对象的副本,然后对象进行扩展,最后返回这个对象。这个扩展的过程就可以理解是一种继承。这种继承的优点就是对一个简单对象实现继承,如果这个对象不是自定义类型时。缺点是没有办法实现函数的复用。

(6)第六种方式是寄生式组合继承,组合继承的缺点就是使用超类型的实例做为子类型的原型,导致添加了不必要的原型属性。寄生式组合继承的方式是使用超类型的原型的副本来作为子类型的原型,这样就避免了创建不必要的属性。

 34  哪些情况会导致内存泄漏

以下四种情况会造成内存的泄漏:

意外的全局变量:由于使用未声明的变量,而意外的创建了一个全局变量,而使这个变量一直留在内存中无法被回收。

被遗忘的计时器或回调函数:设置了setInterval定时器,而忘记取消它,如果循环函数有对外部变量的引用的话,那么这个变量会被一直留在内存中,而无法被回收。

脱离DOM的引用:获取一个DOM元素的引用,而后面这个元素被删除,由于一直保留了对这个元素的引用,所以它也无法被回收。

闭包:不合理的使用闭包,从而导致某些变量一直被留在内存当中。

闭包全局来讲一个函数可以访问它外部的成员,这个函数就可以称之为闭包函数。

闭包是通过改变JS回收机制保留某段作用域的一种手段。当一个函数执行完毕后,里面的局部变量是会被JS自带的垃圾回收机制给销毁的,从而释放内存。但是如果返回一个函数,而且函数里面有用到父级数声明的变量,那么此时,变量不会被回收,因为还有可能被用到,并且外界可以通过函数访问这段作用域下的变量。
 


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值