JavaScript基础
1.get请求传参的误区长度的误区。
提到这个问题就要想到get请求和post请求的差别。
get请求传参通过url明文传输,post请求通过requestbody传参。因此get请求安全性较低。
get请求传参有长度限制,post请求传参没有长度限制
get请求产生一个数据包,post请求产生两个数据包。
而提到get请求传递参数的误区。就是其实get请求并没有规定参数的长度,不过get请求通过url传参,url有长度限制而间接的限制了get传递参数的长度。
2.补充get请求和post请求在缓存方面的区别
get请求一般用户数据的查找和获取,因此可以通过缓存来读取数据
而post请求一般用于修改和更新数据,不能使用缓存
3.说一下闭包
首先说个定义 闭包是指能访问到其他函数内部变量的函数
优点:有利于封装 因为函数内部的变量不能被外部访问到
缺点:内存占用较大 因为闭包里的变量不会被js的垃圾回收机制回收
手撕闭包
function fn() {
var a = 1
var bibao = function () {
console.log(a)
}
return bibao
}
像上面的bibao函数,可以访问到fn内部的变量,这样的函数叫做闭包
4.说一下类的创建和继承
ES6中提出了类的概念,可以用class直接声明一个类,其实我觉得类本质上还是函数。
结合实例理解
class father {
constructor(name){
console.log(`我是实例化对象必须执行的构造函数,你传来的参数是${name}`)
}
show(){
console.log('我是父亲独有的方法')
}
}
class child extends father{
constructor(name){
super(name)
}
show(){
super.show()
}
}
new father('父亲')
new child('儿子')
5.如何解决异步回调地狱
首先知道,什么是异步回调地狱,如果一个函数要用到另一个函数的返回值作为参数,就需要将函数写到函数内部进行调用,如果是很多函数一层一层嵌套下来,代码难以理解和维护。
需要用到promise。手撕一个promise
function f() {
return new Promise(resolve => {
setTimeout(resolve,1000)
})
}
f().then(function () {
console.log(1)
return f()
}).then(function () {
console.log(2)
return f()
})
6.说说前端中的事件流
先捕获再冒泡
7.说一说事件委托
利用的是事件冒泡的原理,让父标签代替子标签执行某些操作。
8.说一下图片的懒加载和预加载
图片懒加载是一种减轻服务器压力的代码优化方案。其表现在不加载网站的所有图片。只加载展示在用户视觉窗口中的图片,等待用户浏览到图片位置时再进行加载。
而图片预加载正好相反,是预先加载图片。避免用户浏览图片出现白屏情况,用户体验感较好。
图片懒加载的实现是使用js的offset,clientheight等一系列函数判断用户的视觉窗口距离网站顶部的高度借此判断用户有没有浏览到图片区域。
9.mouseover和mouseenter的区别
mouseover在鼠标进入元素和其子元素都会触发此函数
mouserenter只在鼠标进入目标元素时会触发函数。
10.js的new操作符做了哪些事情
new先新建了一个空对象,并将此空对象的_proto_属性指向了构造函数的prototype,再执行构造函数,并将实例化后的对象赋值给变量。
12. 改变函数内部this指针的指向函数(bind,apply,call的区别)
bind函数创建之后立即执行
apply函数和call函数创建之后通过调用执行。
apply函数和call函数唯一的区别是传参方式不同,apply函数参数是数组,call函数参数用逗号隔开。
13.js的各种位置,比如clientHeight,scrollHeight,offsetHeight ,以及scrollTop, offsetTop,clientTop的区别?
结合图片顾名思义,clientHeight和clientWidth我们可以理解为是元素内容区域的宽和高。scrollHeight就是元素内容的高度区域再加上被scroll滚动条隐藏起来的区域。offsetHeight:包括元素的边框、内边距和元素的水平滚动条(如果存在且渲染的话),是一个整数。offsetTop距离父元素的高度,clientTop。。。。唔我认为其实就是元素的宽度。。。
14.js拖拽功能的实现
根据逻辑来写就行,mousedown,判断鼠标按下时的鼠标位置,再根据mouseup判断鼠标落下来的鼠标位置实现拖拽功能
15.异步加载js的方法
网上找到的很好的解释
没有 defer
或 async
,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script
标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。
有 async
,加载和渲染后续文档元素的过程将和 script.js
的加载与执行并行进行(异步)。
有 defer
,加载后续文档元素的过程将和 script.js
的加载并行进行(异步),但是 script.js
的执行要在所有元素解析完成之后,DOMContentLoaded
事件触发之前完成
其实应用最多的还是defer属性,正常业务中的需求还是等到页面加载完再执行js代码。
16.js 的节流和防抖
节流和防抖都是为了解决js中如果需要在一个需要高频率触发的动作中执行函数(比如页面的缩放,页面的滚动等),需要浪费很大的资源,节流是指将多次操作合并成一次执行。防抖是指在规定的时间范围内只执行一次函数
17.js的垃圾回收机制
一般有两种方法,标记清除,和计数引用。计数引用有弊端,在两个对象相互引用时无法生效。
18.eval是做什么的
eval可以将字符串解析成js代码并执行。性能消耗较大。
19.说一下Commonjs、AMD和CMD
AMD主要是为了解决模块之间存在的依赖问题和阻塞页面加载的问题。
AMD推崇依赖前置,CMD推崇就近依赖。
20.对象深度克隆的简单实现
最简单的实现方法
function deepclone(obj) {
return JSON.parse(JSON.stringify(obj))
}
常规实现方法
function deepclone(obj) {
var obj_1 = obj instanceof Array ? []:{}
for (var item in obj){
var temp = typeof (obj[item]) == 'Object' ? deepclone(item):item
obj_1[item] = temp
}
return obj_1
}
21.js监听对象属性的变化
用Object的defineproperty来重新定义对象的set方法。
ES6的对象代理
28. setTimeout、setInterval和requestAnimationFrame之间的区别
setTimeout延时触发 setInterval 设置触发间隔 两者和requestAnimationFrame的区别为前两者需要等待之前的代码执行完毕才能执行。而requestAnimationFrame是以系统的时间间隔为标准,无需等待之前代码执行完成。
进击的JavaScript
1.自己实现一个bind函数
if (!Function.prototype.bind){
Function.prototype.bind = function () {
var self = this
var context = [].shift.call(arguments)
var args = [].splice.call(arguments)
return function () {
self.apply(context,[].concat.call(args,[].splice.call(arguments)))
}
}
}
2.用setTimeout来实现setInterval
function setInter() {
console.log(1)
setTimeout(setInter,1000)
}
可以说很简单了,递归调用即可。
3.js代码的执行顺序
介个问题笔试考的多喔!一般是给出一段代码问执行结果是什么。
先执行主队列中的代码,也就是代码中的同步部分,再执行process.then,再是promise.then中的内容,再是setTimeout,setInterval,setImmediate
4.Function.proto(getPrototypeOf)是什么?
答:还是Function
5.js判断类型
instance of
6.数组常用方法
shift unshifit reverse push unpush splice等。
7.数组去重
常规法
function deleteSame(arr) {
var new_arr = []
for (let i = 0; i < arr.length; i++)
if (arr.indexOf(arr[i]) == i)
console.log(arr[i])
return new_arr
}
ES6 new set法
console.log(new Set(arrlist))
还可以将数组的每一项放入对象中,利用对象的属性名不能重复的特性去除重复元素。
8.去除字符串首尾空格
正则表达式(^/s*)|(/s*$)
9.说说js的语言特性
运行在客户端浏览器上;
不用预编译,直接解析执行代码;
是弱类型语言,较为灵活;
与操作系统无关,跨平台的语言;
脚本语言、解释性语言
10.js实现跨域
就顺便把几种我知道的跨域方法说了吧
CORS跨域资源共享 在服务端设置Access-control-allow-origin即可
JSONP跨域 原理是在script中img的src属性和script的href属性不受同源政策限制。从而可以通过新建一个script标签来实现跨域
缺点是只能使用get方法,服务端必须返回特定格式的数据。
设置document.domain
使用window.name进行跨域 即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限
HTML5中的postMessage跨域
跨域方面收藏了一篇好好的博客喔!
https://www.cnblogs.com/yongshaoye/p/7423881.html
11.ES6的新特性
let const关键字 块级作用域 模板字符串 箭头函数 Promise
12.说一下什么是virtual dom
virtual dom是指根据真实的dom结构,用js对象构建出的一个虚拟的dom,当状态更新时,记录两棵树的差异,并将变化应用到真实的dom树中。virtual dom的本质是在js和dom之间做了一个缓存
13.js实现继承的几种方法
有很多 我只记得四种
原型继承
function father() {
}
function son() {
}
son.prototype = new father()
缺陷:原型继承不能传参 原型上的属性会被所有实例所共享
构造继承
function father() {
}
father.prototype.name='wxs'
function son() {
father.call(this)
}
缺陷:不能继承父类原型上的属性和方法
两者都有缺陷,将两种方式结合起来的新方法:组合继承
function father() {
}
father.prototype.name='wxs'
function son() {
father.call(this)
}
son.prototype = new father()
寄生组合继承:
(function(){
var prototype = object(Father.prototype) \\创建一个父类原型的副本
prototype.constructor = Son \\增强对象,补上因重写原型失去的constructor属性
Son.prototype = prototype \\将副本赋值给子类实例
})();
14.vue的生命周期
beforecreate:实例已经创建,data没有初始化
created: data数据已经加载,可以在此处初始化data数据
beforemount 实例挂载到页面之前,获取不到dom节点
mount 实例已经挂载到页面,可以获取到dom节点
beforeupdate:页面更新之前,可以拿到更新之前的数据
updated:更新之后,可以拿到更新之后的数据
beforedestory 实例销毁之前,在此期间依然可以拿到组件实例和data数据
destory 实例销毁之后,实例组件和数据完全不可用
15.js箭头函数的特性
箭头函数没有this,this沿着作用域链网上指向最近的一个this
箭头函数没有arguments,可以用剩余操作符来实现arguments的功能
16.下划线转小驼峰
function change(str) {
var str_1 = str.split("")
for(let i=0;i
17.使用js实现一个单例模式
var HeadClass = function () { };
var Head = (function () { // 匿名自执行函数
var instance; // 声明一个instance对象
return function () {
if (instance) { // 如果已存在 则返回instance
return instance;
}
instance = new HeadClass() // 如果不存在 则new一个HeadClass对象
return instance;
}
})();
to be continue。。。