手记

前端 课题 0902

第 1 题:(滴滴、饿了么)写 React / Vue 项目时为什么要在列表组件中写 key,其作用是什么?

不带有key,并且使用简单的模板,基于这个前提下,可以更有效的复用节点,diff速度来看也是不带key更加快速的,因为带key在增删节点上有耗时。这就是vue文档所说的默认模式。但是这个并不是key作用,而是没有key的情况下可以对节点就地复用,提高性能。这种模式会带来一些隐藏的副作用,比如可能不会产生过渡效果,或者在某些节点有绑定数据(表单)状态,会出现状态错位。VUE文档也说明了。还有就是key的作用是为了在diff算法执行时更快的找到对应的节点,提高diff速度,但是这个含有争议。

第 2 题:`['1', '2', '3'].map(parseInt)` what & why ?

结果: [1, NaN, NaN]

计算会被转化为:

['1', '2', '3'].map((item, index) => {
	return parseInt(item, index)
})

parseInt(string, radix)

radix 代表进制

没有1进制

3不是2进制

第 3 题:(挖财)什么是防抖和节流?有什么区别?如何实现?

1.防抖

触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间

思路: 每次触发事件时都取消之前的延时调用方法,新建延时

2.节流

高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率

思路: 每次触发事件时都判断当前是否有等待执行的延时函数

第 4 题:介绍下 Set、Map、WeakSet 和 WeakMap 的区别?

Set: 成员不能重复;只有健值,没有健名,有点类似数组;可以遍历,方法有add, delete,has

const set = new Set([1, 2, 3, 4, 4]);

weakSet: 成员都是对象;成员都是弱引用,随时可以消失。 可以用来保存DOM节点,不容易造成内存泄漏;不能遍历,方法有add, delete,has

Map: 本质上是健值对的集合,类似集合;可以遍历,方法很多,可以跟各种数据格式转换

const map = new Map([
  ['name', '张三'],
  ['title', 'Author']
]);

weakMap: 直接受对象作为健名(null除外),不接受其他类型的值作为健名;健名所指向的对象,不计入垃圾回收机制;不能遍历,方法同get,set,has,delete

第 5 题:介绍下深度优先遍历和广度优先遍历,如何实现?

深度优先遍历(DFS),广度优先遍历(BFS),BFS和DFS都是图的算法之一,主要用以处理树状结构,在前端用于搜索dom树,遍历object

深度:

function deepFirstSearch(node,nodeList) {
    if (node) {
        nodeList.push(node);
        var children = node.children;
        for (var i = 0; i < children.length; i++)
        deepFirstSearch(children[i],nodeList);
    }
    return nodeList;
}

广度:

function breadthFirstSearch(node,nodeList) {
    var i = 0;
    if (!(node == null)) {
        nodeList.push(node);
        breadthFirstSearch(node.nextElementSibling,nodeList);
        breadthFirstSearch(node.firstElementChild,nodeList);
    }
    return nodeList;
}

第 6 题:请分别用深度优先思想和广度优先思想实现一个拷贝函数?

var obj = {
  a: 1,
  b: {
    c: 2
  }
}
//深度优先伪代码
function deepCopy (obj, new_obj_child) {
  var new_obj = new_obj_child || {};
  for (var i in obj) {
    if (typeof obj[i] == 'object') {
      new_obj[i] = {}
      copy(obj[i], new_obj[i])
    } else {
      new_obj[i] = obj[i]
    }
  }
  return new_obj
}
//广度优先伪代码
function broadCopy (obj, new_obj_child) {
  var new_obj = new_obj_child || {};
  for (var i in obj) {
    if (typeof obj[i] == 'object') {
      new_obj[i] = {}
    } else {
      new_obj[i] = obj[i]
    }
  }
  for (var i in obj) {
    if (typeof obj[i] == 'object') {
      broadCopy(obj[i], new_obj[i])
    }
  }
  return new_obj
}

第 7 题:ES5/ES6 的继承除了写法以外还有什么区别?

function AA () {
this.aa = 'aa'
}
AA.prototype.getAA = function() {
console.log(this)
return this.aa
}
function BB() {
AA.call(this)
}
BB.prototype = new AA()
BB.prototype.constructor = BB
let bb = new BB()
bb.getAA()

ES5的继承实质上是先创建子类的实例对象,然后再将父类的方法添加到this上(Parent.apply(this)),然后再把原型链继承

class AA {
constructor() {
this.aa = 'aa'
}
getAA() {
console.log(this)
return this.aa
}
}
class BB extends AA {
constructor() {
super()
}
}
let bb = new BB()
bb.getAA()

ES6的继承机制完全不同,实质上是先创建父类的实例对象this(所以必须先调用父类的super()方法,才可使用this关键字,否则报错。),然后再用子类的构造函数修改this实现继承

第 8 题:setTimeout、Promise、Async/Await 的区别

setTimeout 为定时器,定时器到期,执行函数或一段代码

Promise 对象用于表示一个异步操作最终完成及其结果

var promise1 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve('foo');
  }, 300);
});
promise1.then(function(value) {
  console.log(value);
});
console.log(promise1);

async用来定义一个返回AsyncFunction对象的异步函数,他会通过一个隐式Promise返回结果,且写法更像同步函数

function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}
async function asyncCall() {
  console.log('calling');
  var result = await resolveAfter2Seconds();
  console.log(result);
}
asyncCall();

第 9 题:(头条、微医)Async/Await 如何通过同步的方式实现异步

async 函数就是 Generator 函数的语法糖。async 函数就是将 Generator 函数的星号(*)替换成 async,将 yield 替换成 await

async比generator改进有自带执行器,更好的语义,更广的适用性

generator利用"协程"(coroutine),意思是多个线程互相协作,完成异步任务。协程最大优点就是代码的写法非常像同步操作.

async异步函数可以包含await指令,该指令会暂停异步函数的执行(即交出执行权),它调用的函数会继续执行, await收到异步函数返回的隐式Promise/原始值,然后继续执行async函数,并返回结果

第 10 题:(头条)异步笔试题

async function async1() {
    console.log('async1 start'); //2
    await async2();
    console.log('async1 end');  //9
}
async function async2() {
    console.log('async2 start'); //3
    await async3();
    console.log('async2 end');  //7
}
async function async3(){
    console.log("async3") //4
}
console.log('script start'); //1
setTimeout(function() {
    console.log('setTimeout'); //10
}, 0)
async1();
new Promise(function(resolve) {
    console.log('promise1'); //5
    resolve();
}).then(function() {
    console.log('promise2'); //8
});
console.log('script end'); //6

考察:同步异步,宏任务微任务执行顺序



靳肖健

0人推荐
随时随地看视频
慕课网APP