JS进阶篇前端面试题整合二

Ajax 是什么? 如何创建一个Ajax?

AJAX全称是Asychronous JavaScript And Xml(异步的 JavaScript 和 XML)
它的作用是用来实现客户端与服务器端的异步通信效果,实现页面的局部刷新,早期的浏览器并不能原生支持ajax,可以使用隐藏帧(iframe)方式变相实现异步效果,后来的浏览器提供了对ajax的原生支持
其主要通过XMLHttpRequest(标准浏览器)、ActiveXObject(IE浏览器)对象实现异步通信效果
实现方式(gitee上的案例):

var xhr =null;//创建对象 
if(window.XMLHttpRequest){
	xhr = new XMLHttpRequest();
}else{
	xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.open(“方式”,”地址”,”标志位”);//初始化请求 
xhr.setRequestHeader(“”,””);//设置http头信息 
xhr.onreadystatechange =function(){}//指定回调函数 
xhr.send();//发送请求 

Ajax的优缺点

优点:

  • 通过异步模式,提升了用户体验
  • 优化了浏览器和服务器之间的传输,按需获取数据,减少不必要的数据往返,减少了带宽占用
  • Ajax在客户端运行,承担了一部分本来由服务器承担的工作,减少了大用户量下的服务器负载。

缺点:

  • ajax不支持浏览器back按钮
  • 安全问题 AJAX暴露了与服务器交互的细节
  • 对搜索引擎的支持比较弱
  • 破坏了程序的异常机制。

一个页面从输入 URL 到页面加载显示完成,发生了什么?

  • 当发送一个 URL 请求时,不管这个 URL 是 Web 页面的 URL 还是 Web 页面上每个资源的 URL,浏览器都会开启一个线程来处理这个请求,同时在远程 DNS 服务器上启动一个 DNS 查询。这能使浏览器获得请求对应的 IP 地址。
  • 浏览器与远程 Web 服务器通过 TCP 三次握手协商来建立一个 TCP/IP 连接。该握手包括一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在 浏览器和服务器之间传递。该握手首先由客户端尝试建立起通信,而后服务器应答并接受客户端的请求,最后由客户端发出该请求已经被接受的报文。
  • 一旦 TCP/IP 连接建立,浏览器会通过该连接向远程服务器发送 HTTP 的 GET 请求。远程服务器找到资源并使用 HTTP 响应返回该资源,值为 200 的 HTTP 响应状态表示一个正确的响应。
  • 此时,Web 服务器提供资源服务,客户端开始下载资源。
  • 后续HTML页面解析参照前端面试题整合(JS进阶篇)(一)的 html页面怎么解析的?它加载顺序是什么?

JQuery一个对象为何可以同时绑定多个事件

低层实现方式是使用addEventListner或attachEvent兼容不同的浏览器实现事件的绑定,这样可以给同一个对象注册多个事件

对页面某个节点的拖曳

1.    给需要拖拽的节点绑定mousedown,mousemove,mouseup事件
2.    mousedown事件触发后,开始拖拽
3.    mousemove时,需要通过event.clientX和clientY获取拖拽位置,并实时更新位置
4.    mouseup时,拖拽结束
5.    需要注意浏览器边界的情况

gitee上的案例

        function mouseMove(ele,parent) {
            ele.addEventListener('mousedown',moveHandler);
            ele.style.position = 'absolute'
            function moveHandler(e) {
                if (e.type === 'mousedown') {
                    parent.ele = this;
                    parent.point = {
                        x: e.offsetX,y: e.offsetY
                    }
                    parent.addEventListener('mousemove',moveHandler);
                    parent.addEventListener('mouseup',moveHandler);
                } else if (e.type === 'mousemove') {
                    this.ele.style.left = e.x - this.point.x + "px";
                    this.ele.style.top = e.y - this.point.y + "px";
                } else if (e.type === 'mouseup') {
                    parent.removeEventListener("mousemove",moveHandler);
                    parent.ele = null;
                    parent.point = null;
                }
            }
        }

new操作符具体干了什么

  1. 创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
  2. 属性和方法被加入到 this 引用的对象中。
  3. 新创建的对象由 this 所引用,并且最后隐式的返回 this

以下是模拟操作:

new TestObj('str')=function(){
    let obj={};  //创建一个空对象
    obj.__proto__=TestObj.prototype;
    //把该对象的原型指向构造函数的原型对象,就建立起原型了:obj->Animal.prototype->Object.prototype->null
    return TestObj.call(obj,arguments);// 绑定this到实例化的对象上
}

前端开发的优化问题

(1) 减少http请求次数:CSS Sprites,JS、CSS源码压缩、图片大小控制合适;网页Gzip,CDN托管,data缓存 ,图片服务器。
(2) 前端模板 JS+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数
(3) 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。
(4) 当需要设置的样式很多时设置className而不是直接操作style。
(5) 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作。
(6) 避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)。
(7) 图片预加载,将样式表放在顶部,将脚本放在底部  加上时间戳。
(8) 避免在页面的主体布局中使用table,table要等其中的内容完全下载之后才会显示出来,显示比div+css布局慢。

fetch和Ajax有什么不同

  • XMLHttpRequest 是一个设计粗糙的 API,不符合关注分离(Separation of Concerns)的原则,配置和调用方式非常混乱,而且基于事件的异步模型写起来也没有现代的 Promise,generator/yield,async/await 友好
  • fetch 是浏览器提供的一个新的 web API,它用来代替 Ajax(XMLHttpRequest),其提供了更优雅的接口,更灵活强大的功能。
  • Fetch 优点主要有:语法简洁,更加语义化基于标准 Promise 实现,支持 async/await

如何编写高性能的Javascript

  • 使用 DocumentFragment 优化多次 append
  • 通过模板元素 clone,替代 createElement
  • 使用一次 innerHTML 赋值代替构建 dom 元素
  • 使用 firstChild 和 nextSibling 代替 childNodes 遍历 dom 元素
  • 使用 Array 做为 StringBuffer ,代替字符串拼接的操作
  • 将循环控制量保存到局部变量
  • 顺序无关的遍历时,用 while 替代 for
  • 将条件分支,按可能性顺序从高到低排列
  • 在同一条件子的多( >2 )条件分支时,使用 switch 优于 if
  • 使用三目运算符替代条件分支
  • 需要不断执行的时候,优先考虑使用 setInterval

定时器setInterval有一个有名函数fn,setInterval(fn,500)与setInterval(fn(),500)有什么区别?

第一个是重复执行每500毫秒执行一次,后面一个只执行一次。

简述一下浏览器内核

浏览器内核又可以分成两部分:渲染引擎和 JS 引擎。它负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入 CSS 等),以及计算网页的显示方式,然后会输出至显示器或打印机。JS 引擎则是解析 Javascript 语言,执行 javascript 语言来实现网页的动态效果。

JavaScript的属性元数据有哪些?

  • writable : true  属性值可修改 
  • enumerable : true  属性可枚举 
  • configurable : true 属性可重新配置 
  • writable : false  属性值不可修改 
  • enumerable : false  属性不可枚举 
  • configurable : false 属性不可重新配置

懒加载(瀑布流)的实现原理

意义:懒加载的主要目的是作为服务器前端优化,减少请求数或延迟请求数实现原理:先加载一部分数据,当触发某个条件时利用异步加载剩余的数据,新得到的数据,不会影响有数据的显示,同时最大程度上减少服务器的资源消耗
实现方式:
(1)延迟加载,使用setTimeOut或setInterval进行加载延迟
(2)符合某些条件,或触发了某些事件才开始异步下载
(3)可视区加载

我的懒加载文章,以及源码地址

js实现数组去重

双层循环,外层循环元素,内层循环时比较值,如果有相同的值则跳过,不相同则push进数组

        class MyArray extends Array {
            constructor() {
                super(...arguments)
            }
            distinct() {
                var myArr = this,list = []
                for (var i = 0; i < myArr.length; i++) {
                    for (var j = i + 1; j < myArr.length; j++) {
                        if (myArr[i] === myArr[j]) {
                            j = ++i;
                        }
                    }
                    list.push(myArr[i]);
                }
                return list;
            }
        }
        var _arr = new MyArray(4,5,6,7,1,2,8,4,9);
        console.log(_arr.distinct()); //[7,9]

利用对象的属性不能相同的特点进行去重

        class MyArray extends Array {
            constructor() {
                super(...arguments)
            }
            distinct() {
                var myArr = this,list = [],obj = {}
                for (var i = 0; i < myArr.length; i++) {
                    obj[myArr[i]] || (obj[myArr[i]] = 1,list.push(myArr[i])) //如果能查找到,证明数组元素重复了
                }
                return list;
            }
        }
        var _arr = new MyArray(4,9);
        console.log(_arr.distinct()); //[4,9]

Set数据结构,它类似于数组,其成员的值都是唯一的

        function dedupe(array) {
            return Array.from(new Set(array));
        }
        console.log(dedupe([1,3])) //[1,3]

实现快速排序和冒泡排序

快速排序:选取位置在数组中间的一个数,然后比它小的放在left[]的一个新数组里面,比他大的放在right[]的一个新数组里面,以此类推,重复执行这个过程,利用递归的思想,直至执行到left[]和right[]里面都只有一个数
冒泡排序:两两比较,前面的比后面的大,则换位。第一轮list.length-1次,挑出最大的;第二轮list.length-1-1次,挑出第二大的。以此往复

        class MyArray extends Array {
            constructor() {
                super(...arguments)
            }
            quickSort(list) { //快速排序
                var myArr = this,listConfig = {
                        midItem: myArr[parseInt(myArr.length / 2)],leftList: new MyArray(),rightList: new MyArray()
                    }
                if (myArr.length <= 1) {
                    return myArr
                };
                for (var i = 0; i < myArr.length; i++) {
                    myArr[i] < listConfig.midItem ? listConfig.leftList.push(myArr[i]) : myArr[i] > listConfig
                        .midItem ? listConfig.rightList.push(myArr[i]) : '';
                }
                return listConfig.leftList.quickSort().concat([listConfig.midItem],listConfig.rightList
                    .quickSort()); //递归
            }
            bubbleSort() { //冒泡排序
                for (var i = 0; i < this.length - 1; i++) {
                    for (var j = 0; j < this.length - 1 - i; j++) {
                        if (this[j] > this[j + 1]) {
                            var item = this[j];
                            this[j] = this[j + 1];
                            this[j + 1] = item;
                        }
                    }
                }
                return this
            }
        }
        var quickSortArray = new MyArray(19,15,18,17,11,21,14,61,13,10,25);
        var bubbleSortArray = new MyArray(9,3,25);
        console.log(quickSortArray.quickSort()); //[10,19,25,61]
        console.log(bubbleSortArray.bubbleSort()); //[1,9,25]

谈谈节流和防抖,如何实现

节流:使频繁执行的函数,定时执行,高频率函数执行时,使执行率减少,每n秒才能执行一次,打个比方:每隔1秒钟,会执行5次滚动条滚动事件,我只让它每一秒执行一次(案例:网站中的返回顶部)

防抖:使频繁执行的函数,延时执行,高频率函数执行时,n秒内只执行一次,在事件内多次执行会延时,打个比方:用户在输入框中输入字符,当用户一直在输入时,我们做个延时,当用户输入完毕后会有一段时间停顿,若这个停顿时间大于我们的我们延时时间,我们就进行下一步操作,反之则不进行并且一直延时(案例:搜索引擎搜索输入框)

区别:对于高频率执行函数,节流是每隔规定时间都会执行一次,防抖是只在规定时间外的最后一次执行

实现过程:

        var count = 0
        class OptimizeEvent {
            constructor() {}
            throttle(fn,time) { //节流
                var canDo = true
                return function (e) {
                    if (!canDo) {
                        return false
                    }
                    canDo = false
                    setTimeout(() => {
                        fn.call(this)
                        canDo = true
                    },time)
                }
            }
            debounce(fn,time) { //防抖
                var _timer = null
                return function () {
                    if (_timer) {
                        clearTimeout(_timer)
                        _timer = null
                    }
                    _timer = setTimeout(fn,time)
                }
            }
        }
        var _event = new OptimizeEvent()
        inputBox.addEventListener('input',_event.debounce(function () {
            showBox.textContent = inputBox.value
        },1000))
        document.addEventListener('scroll',_event.throttle(function () {
            console.log(count++)
        },1000))

谈谈深拷贝的实现

深拷贝相对浅拷贝不同的是,深拷贝内所有引用类型属性值都是在新开辟的内存地址,被拷贝的原数据发生改变时不会影响复制后的对象。

常见方法

  • JSON.parse(),JSON.stringify()
  • jQury的$.extend(true,{},obj)
  • lodash_.cloneDeep
  • 我的深复制文章
    
    			function deepClone(org,tag) {
    				var tag = tag || {}; //初始化要复制的对象
    				var name = Object.getOwnPropertyNames(org); //获取该对象的属性名,以字符串数组返回
    				for (var i = 0; i < name.length; i++) { //遍历对象
    					var desc = Object.getOwnPropertyDescriptor(org,name[i]); //获取对象的属性描述对象,无引用关系,返回另一个对象,改变时原对象不发生变化(复制的关键)
    					if (typeof desc.value === 'object' && desc.value !== null) { //若遍历的每一项非空且为对象,则为引用值,则进行下一步
    						var obj = desc.value.toString() === '[object Object]' ? {} : []; //判断是数组还是对象
    						Object.defineProperty(tag,name[i],{ //设置对象属性值,前三个的值是返回true或false
    							configurable: desc.configurable,//是否可删除可替换
    							enumerable: desc.enumerable,//是否可枚举可遍历
    							writable: desc.writable,//是否可写入
    							value: obj //对象的值
    						});
    						copyObj(desc.value,obj); //再次执行函数
    					} else {
    						Object.defineProperty(tag,desc); //否则直接将该对象的属性值进行复制(原始值)
    					}
    				}
    				return tag;
    			}
    

    常用的对象方法有哪些

  • 添加或更改对象属性
    Object.defineProperty(object,property,descriptor)

  • 添加或更改多个对象属性
    Object.defineProperties(object,descriptors)

  • 访问属性
    Object.getOwnPropertyDescriptor(object,property)

  • 以数组返回所有属性
    Object.getOwnPropertyNames(object)

  • 以数组返回所有可枚举的属性
    Object.keys(object)

  • 访问原型
    Object.getPrototypeOf(object)

  • 阻止向对象添加属性
    Object.preventExtensions(object)

  • 如果可将属性添加到对象,则返回 true
    Object.isExtensible(object)

  • 防止更改对象属性(而不是值)
    Object.seal(object)

  • 如果对象被密封,则返回 true
    Object.isSealed(object)

  • 防止对对象进行任何更改
    Object.freeze(object)

  • 如果对象被冻结,则返回 true
    Object.isFrozen(object)

实现以下输出

       var a = ?
        if (a == 1&& a == 2 && a == 3) {
            console.log('回答正确')
        }
        // 打印回答正确
    class ConsoleA{
        constructor(){
            this.num = 0
            this.valueOf()
        }
        valueOf(){
            return this.num++
        }
    }
    var a = new ConsoleA()
        if (a == 1&& a == 2 && a == 3) {
            console.log('回答正确')
        }
        // 打印回答正确

因为直接调用a==1会进行隐式类型转换从而调用object的valueOf函数

思考以下代码输出,为什么?

var num = 9
switch (num) {
    default:
        console.log('default')
    case 1:
        console.log(1)
    case 2:
        console.log(2)
        break
}

输出   default  1   2
一般情况下default放在switch最后,作为类似于else的作用,而写在switch最上面就相当于if(true),而switch的特点是进入case之后不break跳出来就会一直执行而不做条件判断,所以后面case中的代码都会运行

原文地址:https://blog.csdn.net/time_____

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


1==&gt;简述一下src与href的区别 src用于替换当前元素; href用于在当前文档和引用资源之间确立联系 2==&gt;、谈谈以前端角度出发做好SEO需要考虑什么? a.&#160;了解搜
什么是window对象?什么是document对象? window对象代表浏览器中打开的一个窗口。 document对象代表整个html文档。实际上, document对象是window对象的一个属性
1 》vue-router有哪几种导航钩子? 第一种:是全局导航钩子:router.beforeEach(to,from,next) 第二种:&#160;组件内的钩子 beforeRouteEnter
1=&gt;为什么data是一个函数 【理解】 组件的data写成一个函数, 这样每复用一次组件,就会返回一分新的data。 也就说:给每个组件实例创建一个私有的数据空间。 各个组件维护各自的数据。
01 vue3的新特征 1.组合式API. setUp作为组合函数的入口函数 2.Teleport 传送门 3.片段 template下可以有多个标签 4.用于创建自定义渲染器。我的理解是 creat
// var&#160;arr=[1,2,23,23,4,5,5]; // var&#160;newarr=new&#160;Set(arr);&#160;//去重 // console.log([.
摆好姿势 摆好姿势 如何使下面的等式成立 if(a==1&amp;&amp;a==3&amp;a==5){ console.log(666) } var a=[1,3,5] a.join=a.shif
1=&gt;为什么data是一个函数 【理解】 ok 每复用一次组件,就会返回一分新的data。 也就说:【每个组件实例创建】一个【私有】的数据空间。各个组件维护各自的数据。 如果单纯的写成对象形式,
以下是收集一些面试中经常会遇到的经典面试题以及自己面试过程中无法解决的问题,通过对知识的整理以及经验的总结,重新巩固自身的前端基础知识,如有错误或更好的答案,欢迎指正。:) 在网页中,一个元素占有空间
1 Action是不是线程安全的?如果不是 有什么方式可以保证Action的线程安全?如果是,说明原因不是声明局部变量,或者扩展RequestProcessor,让每次都创建一个Action,或者在s
解决js兼容性问题使用 event对象 function eventHandler(event) { event = event || window.event} 获取滚动条属性 var scrollTop = document.documentElment.scrollTop || document.body.scrollTop
浏览器的内核 IE: trident内核,Firefox:gecko内核,Safari:webkit内核,Opera:以前是presto内核,Opera现已改用Google Chrome的Blink内核,Chrome:Blink(基于webkit,Google与Opera Software共同开发) HTML中的Doctype有什么作用 此标签可告知浏览器文档使用哪种HTML或XHTML规范。(重点:告诉浏览器按照何种规范解析页面) div+css的布局较table布局有什么...
如何创建函数第一种(函数声明): function sum1(num1,num2){ return num1+num2; } 第二种(函数表达式): var sum2 = function(num1,num2){ return num1+num2; } 第三种(函数对象方式): var sum3 = new Function("num1","num2","return num1+num2");三种弹窗的单词以及三种弹窗的功能1.alert //弹出对话框并输出一段提示信...
js的垃圾回收机制是什么原理垃圾回收机制有两种方法第一种是标记清除法:当变量进入执行环境时,就标记这个变量为”进入环境”,当变量离开环境的时候,则将其标记为”离开环境”,垃圾收集器在运行的时候会给储存在内存中的所有变量都加上标记,然后它会去掉环境中的标量以及被环境中的变量引用的标记,而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了,最后,垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收他们所占用的内存空间 第二种是引用计数法:当声明了一个变量并将
Ajax 是什么? 如何创建一个Ajax?AJAX全称是Asychronous JavaScript And Xml(异步的 JavaScript 和 XML)它的作用是用来实现客户端与服务器端的异步通信效果,实现页面的局部刷新,早期的浏览器并不能原生支持ajax,可以使用隐藏帧(iframe)方式变相实现异步效果,后来的浏览器提供了对ajax的原生支持其主要通过XMLHttpRequest(标准浏览器)、ActiveXObject(IE浏览器)对象实现异步通信效果实现方式(gitee上的案例):
谈一谈let与var和const的区别let为ES6新添加申明变量的命令,它类似于var,但是有以下不同: let命令不存在变量提升,如果在let前使用,会导致报错let暂时性死区的本质,其实还是块级作用域必须“先声明后使用”的性质,let 暂时性死区的原因:var 会变量提升,let 不会。let,const和class声明的全局变量不是全局对象的属性const可以在多个模块间共享const声明的变量与let声明的变量类似,它们的不同之处在于,const声明的变量只可以在声明时赋值,不可
解释一下为何[ ] == ![ ] // ---&gt; true首先看一张图![ ] 是 false原式:[ ] == false根据第八条,false通过tonumber()转换为0原式:[ ] == 0根据第十条,[ ]通过ToPrimitive()转换为' '原式:' ' == 0根据第六条原式:0 == 0尝试实现new function ObjectClass() {//对象 console.log(arguments[...
谈谈对Node的理解Node.js 在浏览器外运行V8 JavaScript引擎,单线程 非阻塞I/O 事件驱动,适应于数据高并发,适合多请求,但不适合高运算,有权限读取操作系统级别的API,npm 仓库,常用框架:Express,koa,Socket.io,AdonisJs,NestJS什么是gulp?作用?机制是什么?gulp是基于node的自动化构建工具作用:1 自动压缩JS文件2 自动压缩CSS文件3 自动合并文件4 自动编译sass5 自动压缩图片6 自动刷
vue和react的区别React严格上只针对MVC的view层,Vue则是MVVM模式virtual(虚拟) DOM不一样,vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。而对于React而言,每当应用的状态被改变时,全部组件都会重新渲染,所以react中会需要shouldComponentUpdate这个生命周期函数方法来进行控制组件写法不一样,React推荐的做法是 JSX + inline style,也就是把HTML和CSS全都写进JavaScript了,即'all in
谈谈对react的理解react是基于v(视图层)层的一款框架,虚拟dom和diff算法react特点:声明式设计高效,其中高效以现在虚拟dom,最大限度减少与dom的交互和diff算法灵活,体现在可以与已知的框架或库很好的配合JSX,是js语法的扩展组件化,构建组件,是代码的更容易得到复用,比较建议在大型项目的开发单项数据,实现单项数流,从而减少代码复用react有哪几个生命周期自己的总结分为三个阶段,初始,运行中,销毁初始化: 执行getDefaultProps钩子