鹅厂初面总结

2,961 阅读6分钟

  今天总结一下鹅厂初面的经历,是远程视频面,本来最晚面试时间是七点的,但因为我还在实习晚上六点半才下班,面试官帮我延迟到了八点,挺不好意思的。总的来说面试问的问题不难,面试官也挺好的,虽然面试前做好了被虐的准备,但是真正面试的时候,心态没有摆正还是紧张了,回答的不好,秋招首战算是凉凉了。。

目录

  • 异步处理发展的过程
  • 前端跨域问题处理方法
  • 什么是预请求,何时会触发
  • ES6类声明与构造器原型继承的区别
  • 子类怎样调用父类同名方法
  • 说一下你的项目,具体做了哪些模块
  • 有什么问题想问的吗

异步处理发展的过程

  我们都知道,js是一个单线程的执行环境,原因是js最初只是用来做简单的浏览器交互,操作一下DOM,如果设计成多线程的话,操作DOM有可能出现问题,比如一个线程读取DOM节点数据的同时,另一个线程把那个DOM节点删了。。所以设计者认为js一个线程就够了,代码一步一步顺序执行;但如果一个任务耗时很长的话,后面的任务必须排队等着,这样可能会造成浏览器无响应,用户体验不好,为了解决这个问题,js语言的执行模式分为两种:同步和异步。在浏览器端,耗时长的操作都应该异步执行,处理异步的几种方法:

回调函数

  什么叫回调函数?回调是一个函数被作为一个参数传递到另一个函数里,在那个函数执行完后再执行。

举个栗子 有两个函数f1和f2,后者等待前者的执行结果,如果f1是一个很耗时的任务,就可以考虑改写f1,把f2写成f1的回调函数

function f1(callback){
    // 把代码放到异步处理
    setTimeout(function () {
    // f1 的代码
    callback()
    }, 1000);
}

f1(f2)

如果出现多个回调嵌套时,就可能出现回调地狱问题

总结: 回调函数是异步编程的基本方式,其优点是简单、容易理解,缺点是代码高度耦合,流程比较混乱,不符合我们的思维方式。

事件监听

这种方式是采用事件驱动模式,任务的执行不取决代码的顺序,而取决于监听的事件是否发生。 还是以f1 和f2为例,采用事件监听和改写成:

// 设置监听事件
f1.on('done', f2)
function f1 () {
    // f1 的代码
    //执行完代码后触发事件
    f1.trigger('done')
}

总结: 这种方法可以绑定多个事件,每个事件可以指定多个回调函数,而且看出代码松耦合,有利于实现模块化;缺点是整个程序变成是事件驱动型,流程可能变得不清晰

Promise

PromiseES6新增的一个异步编程的选择

还没了解Promise用法的同学可以看这里 传送门

使用Promise改写上面的例子

var p = new Promise((resolve, reject) => {
    setTimeout(() => {
        // f1 的代码
        console.log('start f1')
        // 执行完毕后
        resolve('success')
    }, 1000)
})
p.then(f2)

当有多个回调函数时

f1().then(f2).then(f3)

总结:使用Promise可以将回调函数写成链式调用,程序执行流程清楚

async await

await语法是ES2017确定的异步编程方式,其可以将异步代码当作同步代码来书写

举个栗子

function getCode(){
  return axios.get('json/code.json');
}
function getlist(params){
  return axios.get('json/person.json',{params})
}

// promise处理

function getResult () {
    getCode().then(res => {
        const res = res.data
        if (res.code) {
            const params = res.id
            getList(params).then(list => {
                console.log('获取到最终数据' + list)
            })
        }
    })
}
getResult()

// await处理

async function getResult () {
    const res = await getCode()
    const params = res.data.id
    const list = await getList(params)
    console.log('获取到最终数据' + list)
}

await意思是等一下,它会将后面的函数包装为Promiseawait会在Promise被 拒绝的情况下抛出错误,否则它将返回该Promise被决议的值。由上面的栗子看出,await处理异步比Promise更为优雅

前端跨域问题处理方法

这个问题我有总结过,传送门

什么是预检请求,何时会触发

这个问题之前没怎么了解,没回答上来,有点尴尬

预请求是跨域资源共享(CORS)标准规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求求),浏览器必须首先使用OPTIONS方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求

发送预检请求的条件

  • 使用了PUT,DELETE,CONNECT,OPTIONS等HTTP方法
  • 人为设置了对CORS安全的首部字段集合之外的其他首部字段
  • Content-type的值不属于下列之一:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

举个栗子 一个需要执行预检请求的HTTP请求

var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/post-here/';
var body = '<?xml version="1.0"?><person><name>Arun</name></person>';
    
function callOtherDomain(){
  if(invocation)
    {
      invocation.open('POST', url, true);
      invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
      invocation.setRequestHeader('Content-Type', 'application/xml');
      invocation.onreadystatechange = handler;
      invocation.send(body); 
    }
}

发送的预检请求会携带下面两个首部字段:

Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type

预检请求的响应为:

Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400

ES6类声明与构造器原型继承的区别

主要的区别有:

  • 类表达式/类声明的函数都不会被提升,与let相识,存在临时性死区
  • 代码自动运行在严格模式下,且无法退出
  • 不能缺少new调用
  • class函数内部无法重写类名
  • 类所有方法都没有[[constuct]]指针,即不能使用new调用,不可枚举
  • 能动态的决定所要继承的类,因为extends接受任意能返回具有[[Construct]]属性的函数的表达式

以上是我总结出的两者间的区别,有什么遗漏或错误的地方欢迎提出

子类怎样调用父类同名方法(子类的原型是父类)

ES5的方法

let person = {
    sayHello () {
        return 'Hello'
    }
}
let friend = {
    sayHello () {
        return Object.getPrototypeOf(this).sayHello.call(this)
    }
}

Object.setPrototypeOf(friend, person)
console.log(friend.sayHello()) // Hello

ES6的方法

let person = {
    sayHello () {
        return 'Hello'
    }
}
let friend = {
    sayHello () {
        return super.sayHello()
    }
}

Object.setPrototypeOf(friend, person)
console.log(friend.sayHello()) // Hello

说一下你的项目,具体做了哪些模块

这个就不说了~

有什么问题想问的吗

  面了大概四十多分钟,整个面试我都表现的不好,当面试官说有什么问题想问的吗,我想直接一点,就问了我有机会进入下一轮面试么。。面试官说得回去评估一下

总结

  虽然这次面试失败了,总的来说也是一个不错的体验,发现了自己一些不足的地方。很快就到九月份了,还是静下心来好好准备秋招吧