面试ajax上机,前端基础面试题@JS篇

说说Js的数据类型都有哪些

基本类型

String

Number

Boolean

null

undefined

symbol

引用类型

object

说说Http状态码

1** 信息,服务器收到请求,需要请求者继续执行操作(101,升级为websocket协议)

2** 成功,操作被成功接收并处理(206,部分内容,分段传输)

3** 重定向,需要进一步操作以完成请求(301,302重定向;304命中缓存)

4** 客户端错误,请求包含语法错误或无法完成请求(401,要求身份验证;403,服务器理解客服端需求,但是禁止访问)

5** 服务器错误,服务器在处理请求的过程中发生了错误

说说ajax状态码,ajax一定是异步的吗?

ajax不一定是异步的,可以通过open方法的第三个参数来配置(默认为true,异步)

状态码:

0 - (未初始化)还没有调用send()方法

1 - (载入)已调用send()方法,正在发送请求

2 - (载入完成)send()方法执行完成

3 - (交互)正在解析响应内容

4 - (完成)响应内容解析完成,可以在客户端调用了

说说ajax是什么?优势?劣势?应该注意的问题?

ajax是一种和后台通信的标准。全称是Asynchronous Javascript And XML(异步javascript和XML)。

优势:

无需刷新页面请求数据,可以使产品更快、更小、更友好

可以把以前服务端的任务转嫁到客户端来处理,减轻服务器负担,节省带宽

浏览器支持好,无需插件

劣势:

不支持浏览器的回退按钮

安全性存在问题,能够在用户不知情的情况下发送请求

暴露了http交互细节

对搜索引擎(网络爬虫)的支持比较弱

程序不容易调试

注意的问题:

浏览器兼容性问题,这个问题jQuery等库已经帮我们封装好了

跨域问题,不同域之间不允许通过ajax进行访问,可以参考阮一峰老师的跨域资源共享 CORS 详解

为了更快的速度和对搜索引擎友好,首页尽量不要用ajax而是服务端渲染(当然这看分场景)

ajax适合增删改查操作

你把下面的表达式的打印结果写出来

1.toString() //Uncaught SyntaxError: Invalid or unexpected token

true.toString() //"true"

[].toString() //""

{}.toString() //Uncaught SyntaxError: Unexpected token .

null.toString() //Uncaught TypeError: Cannot read property 'toString' of null

undefined.toString() //Uncaught TypeError: Cannot read property 'toString' of undefined

NaN.toString() //"NaN"

复制代码

这些需要刻意背一下,其中1和{}是语法错误。null和undefined是因为没有toString方法,可以使用call来借用(想详细了解,可以到评论区看我如何被骂的):

1..toString() //"1"

(1).toString() //"1"

Number(1).toString() //"1"

({}).toString() //[object Object]

Object.prototype.toString.call(null) //[object Null]

Object.prototype.toString.call(undefined) //[object Undefined]

复制代码

前端性能优化你了解哪些

内容层面

使用CDN

单域名、多域名,单域名可以减少DNS查找次数,多域名可以增加浏览器并行下载数量,这需要权衡,一般同一个域下不要超过四个资源。

避免重定向(分场景)

避免404

网络层面

文件压缩(通过响应头Accept-Encoding: gzip, deflate, br告诉服务器你支持的压缩类型)

按需加载,提取公共代码,tree-shaking等(都可以通过webpack来实现)

减少cookie大小

文件合并,通过css雪碧图合并图片

文件预加载、图片懒加载

渲染层间

js放底部,css放顶部

减少reflow(回流)和repaint(重绘)

减少dom节点

代码层面

缓存dom节点,减少节点查找,css选择器层级优化

减少dom节点操作

合理使用break、continue、return等,优化循环

像react用到的事件委托、对象池等手段

说说浏览器的reflow和repaint

浏览器解析过程

解析html生成dom树

解析css

把css应用于dom树,生成render树(这里记录这每一个节点和它的样式和所在的位置)

把render树渲染到页面

reflow(回流)

reflow翻译为回流,指的是页面再次构建render树。每个页面至少发生一次回流,就是第一次加载页面的时候

此外,当页面中有任何改变可能造成文档结构发生改变(即元素间的相对或绝对位置改变),都会发生reflow,常见的有:

添加或删除元素(opacity:0除外,它不是删除)

改变某个元素的尺寸或位置

浏览器窗口改变(resize事件触发)

repaint(重绘)

repaint翻译为重绘,它可以类比为上面的第四步,根据render树绘制页面,它的性能损耗比回流要小。每次回流一定会发生重绘。此外,以下操作(不影响文档结构的操作,影响结构的会发生回流)也会发生重绘:

元素的颜色、透明度改变

text-align等

浏览器优化

我们不太容易精确知道哪些操作具体会造成哪些元素回流,不同的浏览器都有不同的实现。但是确定是他们的的耗时是比较长的,因为涉及到大量的计算。

浏览器为了提升性能也对这个问题进行了优化。方案就是维护一个队列,把所有需要回流和重绘的操作都缓存起来,一段时间之后再统一执行。但是,有的时候我们需要获取一些位置属性,当我们一旦调用这些api的时候,浏览器不得不立即计算队列以保证提供的数据是准确的。例如以下操作:

offsetTop, offsetLeft, offsetWidth, offsetHeight

scrollTop/Left/Width/Height

clientTop/Left/Width/Height

width,height

getComputedStyle或者IE的currentStyle

注意问题

批量处理

使用DocumentFragment进行缓存,这样只引发一次回流

把频繁操作的元素先display:null,只引发两次回流

cloneNode和replaceChild,只引发两次回流

不要频繁更改style,而是更改class

避免频繁调用offsetTop等属性,在循环前把它缓存起来

绝对定位具有复杂动画的元素,否则会引起父元素和后续大量元素的频繁回流

如何去除字符串首位空格?

//es6

' ab '.trim() //"ab"

//正则

' ab '.replace(/^\s*|\s*$/g,'') //"ab"

复制代码

如何获取url中的查询字符串

function queryUrlParameter(str) {

let obj = {}

let reg = /([^?=]+)=([^?=]+)/g;

str.replace(reg, function () {

obj[arguments[1]] = arguments[2]

})

//如果加上hash

// reg = /#([^?&=#]+)/g

// if (reg.test(str)) {

// str.replace(reg, function () {

// obj.hash = arguments[1]

// })

// }

return obj

}

console.log(queryUrlParameter('http://www.baidu.com?a=1&b=2#12222')) //{ a: '1', b: '2'}

复制代码

如何实现一个深拷贝、深比较

深拷贝

function clone(obj) {

if (obj == null || typeof obj !== 'object') return obj

let newObj = null

// 时间对象有特殊性

if (obj.constructor === Date) {

newObj = new obj.constructor(obj)

} else {

newObj = obj.constructor()

}

for (let key in Object.getOwnPropertyDescriptors(obj)) {

newObj[key] = clone(obj[key])

}

return newObj

}

复制代码

深比较

function deepCompare(a, b){

if(a === null

|| typeof a !== 'object'

|| b === null

|| typeof b !== 'object'){

return a === b

}

const propsA = Object.getOwnPropertyDescriptors(a)

const propsB = Object.getOwnPropertyDescriptors(b)

if(Object.keys(propsA).length !== Object.keys(propsB).length){

return false

}

return Object.keys(propsA).every( key => deepCompare(a[key], b[key]))

}

复制代码

如何实现函数节流和防抖

节流

function throttle(fn, delay) {

delay = delay || 50

let statTime = 0

return function () {

statTime === 0 && fn.apply(this, arguments)

let currentTime = new Date()

if (currentTime - statTime > delay) {

fn.apply(this, arguments)

statTime = currentTime

}

}

}

let throttleFn = throttle(fn)

throttleFn()//只会执行一次

throttleFn()

throttleFn()

throttleFn()

复制代码

防抖

function debounce(fn, delay) {

delay = delay || 50

let timer = null

return function () {

let self = this

clearTimeout(timer)

timer = setTimeout(fn.bind(self, arguments), delay);

}

}

复制代码

你给我写一个原生bind方法

Function.prototype._bind = function (context) {

let self = this

let args_1 = [].prototype.slice.call(arguments, 1)

return function () {

let args_2 = [].prototype.slice.call(arguments)

let args = args_1.concat(args_2)

return self.apply(context, args)

}

}

复制代码

这只是对bind的一种简单实现,如果有兴趣了解更多可以参考Javascript中bind()方法的使用与实现

如何实现一个数组的展平

function (ary) {

return ary.toString().split(',')

}

复制代码

这是一个投机取巧的方法(面试写个这个也凑合吧),如果有兴趣可以搜索一下其他实现方法

如何添加、删除、移动、复制DOM节点

创建

createTextNode() //创建文本节点

createElement() //创建元素节点

createDocumentFragment() //创建文档碎片

操作

appendChild() //增加

removeChild() //删除

replaceChild() //替换

insertBefore() //插入

查找

getElementById()

getElementByTagName()

getElementByName()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值