A公司(C轮 100-499 一面)
vue keep-alive内置组件
watch和computed区别及应用场景
隐藏DOM的几种方式 position:stick
原型怎么理解
JS基本数据类型,typeof可以有哪几种结果
null和undefined区别
app唤起链接怎么做
混合包的一些问题
B公司(已上市 10000人以上 一面)
笔试:
浏览器跨域
for...in和for...of区别
ie盒子和标准盒子模型及差别
一行代码实现数组去重
arr = Array.from(new Set(arr))
arr = [...new Set(arr)]
str = Array.from(new Set(str)).join('')//字符串去重
str = [...new Set(str)].join('')冒泡排序
一面:
vue-router
导航守卫
route与$router
vuex使用
组件通信
- 父子组件
- 兄弟组件
- 跨级组件
深拷贝,浅拷贝
- 浅拷贝:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
//数组使用concat或slice或[...arr],Array.from等 a1 = [1, 2]; a2 = a1.concat();//ES5 a2 = [...a1];//ES6 a3 = [[1,2], 2]; a4 = [...a1]; a4[0][0] = 2; console.log(a3) //对象使用Object.assign(target,...source)或{...obj} - 深拷贝
//方法1:转成对象JSON或者数组JSON,函数,undefined,symbol经过JSON.strify会丢失 //方法2:使用第三方库,jquery的$.extend和lodash的_.cloneDeep obj = { o:{ a:1, b:2, }, a:1, } obj2 = JSON.parse(JSON.stringify(obj)); obj2.o.a=2; console.log(obj2,obj)
Set和Map使用
- Set
ES6新数据结构。构造函数参数可接受数组或具有iterable接口的其他数据结构用来初始化。通过Array.from()将Set结构转化为Array结构,这样数组的一些方法Set结构就可以间接使用。
set = new Set([1, 2, 3, 4, 4]);
typeof set //'object'
set instanceof Set//true
set//{1, 2, 3, 4}操作方法:add,delete,has,clear方法。
遍历方法:keys,values,entries,foreach方法,Set数据结构支持for...of直接遍历(默认遍历器生成函数就是values),size属性。
使用Set实现交/并/差集。
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 并集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
// (a 相对于 b 的)差集
let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}- Map
ES6新数据结构,相对于传统对象的键名只能是字符串,Map的键名可以是各种类型(包括对象的,是一种更完善的hash结构实现。作为构造函数,Map 也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。不仅仅是数组,任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构都可以当作Map构造函数的参数。这就是说,Set和Map都可以用来生成新的 Map。只有对同一个对象的引用,Map 结构才将其视为同一个键。常用方法和属性同Set,此外,还有set,get方法。Map 的遍历顺序就是插入顺序。Map的默认遍历器实现是使用entries方法。
m = new Map()
typeof m;//'object'
m instanceof Map;//true
m instanceof Object;//true图片懒加载
微服务
总结:部门业务主要是PC端,考察多涉及
浏览器兼容,JS执行原理,基础CSS。可以看出来小姐姐考察点很全面,部门代码质量相对比较高~喜欢~C公司(C轮 500-999 二面)
一面:
BFC盒子
可以通过创建BFC盒子,解决margin折叠问题。
常见的创建条件为:
- overflow:hidden;
- float:left/right;
- position:absolute;
- display:inline-block;
- display:flex;
- 等
手写实现bind函数
call,bind,apply都是JS内置的API,可以改变this指向。
三者区别:
//都只有一个参数时,该参数即为指定的this,类似于执行了this = obj;
obj = {
a:1,
};
function f(){
this.a = 2;
console.log(obj.a)
};
f.call(obj);//直接执行
f.apply(obj);//直接执行
newF = f.bind(obj);//返回一个新函数
newF();
//多参数使用,第一个参数均为指定this,其余参数为函数参数,call和bind支持多参数,apply第二个参数为数组
let obj1 = {
num: 1
};
let obj2 = {
num: 2
}
function fn (x,y) {
console.log(x+y+this.num);
}
fn.call(obj1,1,2); // 4
fn.apply(obj1,[1,2]); // 4
//bind支持函数柯里化:我们在调用_fn之前传入了一部分参数,调用时参入了剩余参数
//方式1
fn.bind(obj1,1,2)();
//方式2
fn.bind(obj1,1)(2);
//方式3
let _fn = fn.bind(obj1,1);_fn(2); // 4PS:函数柯里化,一个函数传入部分参数,返回一个新函数处理剩余参数。
function f(x){
return function(y){
console.log(x+y);
}
}
f(1)(2);//方式1
_f = f(1);//方式2
_f(2);- bind
特点:
1.改变this指向
2.返回一个新函数
3.支持函数柯里化
let obj1 = {
num: 1
};
function fn (x,y) {
console.log(x,y,x+y+this.num);
}
Function.prototype.myBind = function(context,...args){
let fn = this;//构造函数原型上的函数this指向实例,即调用myBind的fn
args = args?args:[];
return function newFn(...newArgs){
if(this instanceof newFn){
return new fn(...args,...newArgs);//args为闭包
}
return fn.apply(context,[...args,...newArgs])
}
}
fn.myBind(obj1,1,2)();
// fn.myBind(obj1,1)(2);
// _fn = fn.myBind(obj1,1,2);
// test = new _fn();
- call
特点:
let obj1 = {
num: 1
};
function fn (x,y) {
console.log(x,y,x+y+this.num);
}
let obj1 = {
num: 1
};
function fn (x,y) {
console.log(x,y,x+y+this.num);
}
Function.prototype.myApply = function(context,...args){//!!!!区别在这里呀,也可以使用arguments类数组
context = context || window;
args = args?args:[];
const key = Symbol();
context[key] = this;//调用实例
let result = context[key](...args);//通过对象调用方式改变this指向
delete context[key]
return result;
}
fn.myApply(obj1,[1,2]);
- apply
特点:第二个参数为数组
let obj1 = {
num: 1
};
function fn (x,y) {
console.log(x,y,x+y+this.num);
}
let obj1 = {
num: 1
};
function fn (x,y) {
console.log(x,y,x+y+this.num);
}
Function.prototype.myApply = function(context,args){
context = context || window;
args = args?args:[];
const key = Symbol();
context[key] = this;//调用实例
let result = context[key](...args);//通过对象调用方式改变this指向
delete context[key]
return result;
}
fn.myApply(obj1,[1,2]);手写防抖、节流
针对持续触发的监听事件,如resize,scroll,touchmove,mousemove等做函数防抖(操作结束后一定时间执行一次)和节流(操作进行过程中固定时间执行多次)。无法控制DOM事件的触发次数,但可以控制DOM监听函数的执行频率。
- 防抖
function debounce(fn,wait){
console.log(1)
let timeout;//形成了闭包
return function(){
let content = this;//this指向与debounce保持一致 存疑...
let args = arguments;//args[0]为event,仍然可以获取event对象
if(timeout) clearTimeout(timeout);
timeout = setTimeout(()=>{
fn.apply(content,args);
},wait)
}
};
function handle(){
console.log(2)
}
//window.onscroll = debounce;只是挂载debounce函数并没有执行
window.onscroll = debounce(handle,1000);//考虑到需要传递行参挂载其他函数,使用return新的function地形式;则执行了debounce函数并挂载了匿名function- 节流
//使用时间戳
function throttle(fn,wait){
console.log(1)
let previous = 0;
return function(){
let content = this;//this指向与debounce保持一致 存疑...
let args = arguments;//args[0]为event,仍然可以获取event对象
let now = new Date();
if(now - previous>wait){
fn.apply(content,args)
previous = now;
}
}
};
function handle(){
console.log(2)
}
window.onscroll = throttle(handle,1000);
//使用定时器
function throttle(fn,wait){
console.log(1)
let timeout;
return function(){
let content = this;//this指向与debounce保持一致 存疑...
let args = arguments;//args[0]为event,仍然可以获取event对象
// if(timeout){ clearTimeout(timeout)}
if(!timeout){
timeout = setTimeout(()=>{
timeout = null;
fn.apply(content,args)
},wait);
}
}
};
function handle(){
console.log(2)
}
window.onscroll = throttle(handle,1000);
this
原型
深浅拷贝
vue源码
双向绑定原理,监听订阅是怎么实现的,具体如何监听的
设计模式使用
闭包使用
box-sizing
width的宽度即为设置的两种值,content-box,border-box。
日常学习方式
完成最好的一次项目经历
职业规划
总结:主要围绕日常开发比较常用的轮子考察,JS基础,CSS基础,框架较少,以及个人特质的考察。
D公司 (未融资 一面)
笔试:
类型转换
目标类型只有boolean,string,number三种。
px,em,rem区别及如何适配
如何减少页面加载时间
使用this的三个场景
cookies,sessionStorage,localStorage的区别
- cookies
- 大小4KB,比较小
- sessionStorage
- 随请求发送
- 可设置过期时间等
- 大小5MB,较大
- 关闭页面或者浏览器
- localStorage
- 大小5MB,较大
- 手动clear()
判断字符串中出现次数最多的字符及对应次数
ajax的优缺点及原理
总结:CSS基础,JS基础,AJAX等。
E公司(已上市 1000-9999 二面)
一面:
px,em,rem优缺点
个别机型表现存在差异。
DOM原生事件绑定的几种方法
- DOM0级(on+type)
只可注册绑定一个,后者会覆盖前者;只支持冒泡阶段。参考。
- DOM2级(addEventListener)
同个DOM可注册多个监听器;第三个options选项可灵活控制各场景,对于touchmove,touchstart手动设置选项passive为true可组织默认连带的滚动行为,使页面触摸更流畅;最好手动原样去除DOM事件removeEventListener。参考。IE9以下的IE浏览器不支持 addEventListener()和removeEventListener(),使用 attachEvent()与detachEvent() 代替,因为IE9以下是不支持事件捕获的,所以也没有第三个参数,第一个事件名称前要加on。
- html(on事件)
阻止默认事件兼容
function preventDef(e){
var g = e || window.event;
if(g.preventDefault){
g.preventDefault();
}else if(g.returnValue){
g.returnValue = false;
}
return false;
}事件流和事件委托/代理
捕获阶段,目标阶段(目标元素身上不区分冒泡捕获,按绑定的前后顺序来执行。),冒泡阶段。
利用事件冒泡的机制,事件最终都会冒泡到祖先元素,只需要给祖先绑定事件就可以监听所有子元素的事件,而不用给每个DOM都绑定事件。同时可以在listener中进行区别处理。
- 可以大量节省内存占用,减少事件注册。
- 可以实现当新增子对象时,无需再对其进行事件绑定,对于动态内容部分尤为合适
- 事件代理的常用应用应该仅限于上述需求,如果把所有事件都用事件代理,可能会出现事件误判。即本不该被触发的事件被绑定上了事件。
event.currentTarget,event.target
event.target指向引起触发事件的元素,而event.currentTarget则是事件绑定的元素,只有被点击的那个目标元素的event.target才会等于event.currentTarget。也就是说,event.currentTarget始终是监听事件者,而event.target是事件的真正发出者。原型
new的原理(this关系挂载,原型关系挂载)
function Animal(type) {
this.type = type;
}
Animal.prototype.say = function() {
console.log('say')
}
function mockNew() {
let Constructor = [].shift.call(arguments); // 取出构造函数
let obj = {} // new 执行会创建一个新对象
obj.__proto__ = Constructor.prototype //原型关系挂载
Constructor.apply(obj, arguments)//this关系挂载
return obj
}
let animal = mockNew(Animal, 'dog')
console.log(animal.type) // dog
animal.say() // say作者:JOKER_链接:https://juejin.cn/post/6844903782803832845来源:掘金著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。原型链
for in,Objects.keys(),for of区别
- for in
- 对象/数组本身及其原型链上的可枚举属性
- 对于自定义数组可枚举属性也可以遍历
- 返回的结果是string类型的对象key和数组索引
- 某些情况下可能按随机顺序遍历数组,不推荐使用此方法遍历数组
- Objects.keys()
- 对象自身及自定义的可枚举属性,不会遍历原型链及
Symbol属性 - 返回的结果是对象key组成的数组
- 对数组的遍历与for in一致
- 此外,Object.entries()返回的是[key,value]二级数组。
- for of
- 支持对数组,类数组对象(NodeList),字符串,Set,Map的遍历
- 对数组的遍历不支持自定义属性(类对象属性)和原型属性
- 不支持遍历普通对象
深浅拷贝
event loop
promise.finally
浏览器跨域
同源策略:相同网络协议,域名,端口号;浏览器安全;
非同源存在的问题:
- 数据:无法获取非同源网页的 cookie、localstorage 和 indexedDB。
- DOM:无法访问非同源网页的 DOM (iframe)。
- 请求:无法向非同源地址发送 AJAX 请求 或 fetch 请求(可以发送,但浏览器拒绝接受响应)。
解决方式:
- 数据:
- window.postMessage :一个 HTML5 的 api,允许两个窗口之间进行跨域发送消息。
- DOM:
- document.domain:
- window.name:
- 请求:
- CORS:服务器端配置。相关响应头信息
Access-Control-Allow-Origin。 - JSONP:前后端配合完成,使用简单且兼容性不错,但是只限于
get请求。
原理就是利用 <script> 标签的 src 属性没有跨域的限制,通过指向一个需要访问的地址,由服务端返回一个预先定义好的 Javascript 函数的调用,并且将服务器数据以该函数参数的形式传递过来
//定义获取数据的回调方法
function getData(data) {
console.log(data);
}
// 创建一个script标签,并且告诉后端回调函数名叫 getData
var body = document.getElementsByTagName('body')[0];
var script = document.gerElement('script');
script.type = 'text/javasctipt';
script.src = 'demo.js?callback=getData';
body.appendChild(script);
//script 加载完毕之后从页面中删除,否则每次点击生成许多script标签
script.onload = function () {
document.body.removeChild(script);
}协商缓存与强制缓存
总结:考察JS原理熟练掌握及灵活应用,浏览器相关。
个人项目介绍
vue
angular
微信小程序
node