阅读 237

面试之复盘(一)

表现

紧张,应该吧,好像是,可能也许大概= =

自信点!-> 是这样!就是这样!

其实主要是准备不充分...

题目

网络安全

什么是XSS、CSRF

  • XSS:跨站脚本(Cross-site scripting,通常简称为XSS)

通过客户端脚本语言(如:JavaScript)在一个论坛发帖中发布一段恶意的JavaScript代码就是脚本注入,如果这个代码内容有请求外部服务器,那么就叫做XSS!

比如用js写一个跨站脚本,携带用户的cookie发送给某个服务器,这个服务器可以利用用户的隐私信息,做其他一些恶意的业务处理(获取用户隐私存入自身数据库等)。注意此时并没有发生CSRF,因为没有冒充用户向其他服务器发起请求,只是将数据存储起来了。

  • CSRF:跨站请求伪造(英语:Cross-site request forgery)

又称XSRF,冒充用户发起请求(在用户不知情的情况下),完成一些违背用户意愿的请求(如恶意发帖,删帖,改密码,发邮件等)。

比如在用户不知情的情况下让他们触发点击某个请求链接,完成非用户本意的一些向其他服务器的请求。注意此时并没有用到XSS,因为没有脚本注入。

微信小程序

小程序工作流程

微信小程序的框架包含两部分View视图层(可能存在多个)、App Service逻辑层(一个),View层用来渲染页面结构,AppService层用来逻辑处理、数据请求、接口调用,它们在两个线程里运行。

视图层使用WebView渲染,逻辑层使用JSCore运行。

视图层和逻辑层通过系统层的WeixinJsBridage进行通信,逻辑层把数据变化通知到视图层,触发视图层页面更新,视图层把触发的事件通知到逻辑层进行业务处理。

双线程模型将逻辑层与视图层进行分离,它们之间只有数据的通信,可以防止开发者随意操作界面,更好地保证用户的数据安全

img

页面渲染具体流程:在渲染层,宿主环境会把WXML转换成对应的js对象,在逻辑层发生数据变更的时候,我们需要通过宿主环境提供的setData方法把数据从逻辑层传递到渲染层,再经过对比前后差异,把差异应用在原来的DOM树上,渲染出正确的ui界面。

ES6

Async await的原理是什么?ES5是如何实现的?

解决函数回调经历了几个阶段, Promise 对象, Generator 函数到async函数。async函数目前是解决函数回调的最佳方案。

  • 用法

async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。

function getNum(num){
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(num+1)
        }, 1000)
    })
}
// 在function外部书写async,在内部需要等待执行的函数前书写await
const func = async ()=>{
    const f1 = await getNum(1)
  const f2 = await getNum(f1)
  console.log(f2) 
  // 输出3 
}
func()
复制代码
  • 原理

async/await实际上是对Generator(生成器)的封装,是一个语法糖。

但二者又有三点不同:

  • async/await自带执行器,不需要手动调用next()就能自动执行下一步
  • async函数返回值是Promise对象,而Generator返回的是生成器对象
  • await能够返回Promise的resolve/reject的值

我们对async/await的实现,其实就是对应以上三点封装Generator。

// 定义了一个promise,用来模拟异步请求,作用是传入参数++
function getNum(num){
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(num+1)
        }, 1000)
    })
}

//自动执行器,如果一个Generator函数没有执行完,则递归调用
function asyncFun(func){
  var gen = func();

  function next(data){
    var result = gen.next(data);
    if (result.done) return result.value;
    result.value.then(function(data){
      next(data);
    });
  }
  
  // 自动执行
  next();
}

// 所需要执行的Generator函数,内部的数据在执行完成一步的promise之后,再调用下一步
var func = function* (){
  var f1 = yield getNum(1);
  var f2 = yield getNum(f1);
  console.log(f2) ;
};
asyncFun(func);
复制代码
  • ES5实现
// 通过 babel 转码之后的 ES5 代码
function _asyncToGenerator(fn) {
  return function() {
    var gen = fn.apply(this, arguments)
    // 返回promise
    return new Promise(function(resolve, reject) {
      function step(key, arg) {
        try {
          // 调用next执行结果
          var info = gen[key](arg)
          // 执行结果的value值
          var value = info.value
        } catch (error) {
          reject(error)
          return
        }
        // 全部执行完毕,执行resolve
        if (info.done) {
          resolve(value)
        } else {
          // 还没有执行完,返回promise
          return Promise.resolve(value).then(
            function(value) {
              step('next', value)
            },
            function(err) {
              step('throw', err)
            }
          )
        }
      }
      // 返回时自动执行
      return step('next')
    })
  }
}
复制代码

Typescript

typescript中type 和 interface的区别?

因为在 Typescript 里 type 和 interface 都能实现类型的定义,因此在一些使用方面他们都很像,都是可以描述一个对象或函数。

  • 使用上
// 使用 type 定义了一个符合类型的别名
type TUserListResult = Promise<{
    total: number,
    list: [{
        title: string,
        id: number,
    }],
}>

// 使用 interface 定义了一个复合类型接口
interface IDataListResult {
    total: number,
    list: [{
        title: string,
        id: number,
    }],
}
复制代码
function (offset: number): TUserListResult {
    return new Promise((resolve, reject) => {
        
    });
}

function getDataList(offset: number): Promise<IDataListResult> {
    return new Promise((resolve, reject) => {
        
    });
}
复制代码
  • 实现继承的表现形式不同
// 与类的继承相似
interface Name {
    name: string;
}
interface User extends Name {
    age: number;
}

// type 利用交叉类型实现的继承
type Name = {
    name: string;
}
type User = Name & { age: number };
复制代码
  • 声明上

type 作为类型的别名,可以轻易的实现声明基本类型别名,联合类型,元组等类型,而 interface 则不行。

此除之外,type 还能通过 typeof 获取类型,并声明。

let div = document.createElement('div');
type B = typeof div;
复制代码

interface 能够声明合并,而 type 不行(会报重复声明错误)。

interface User {
    name: string,
    age: number,
}
interface User {
    sex: string,
}
复制代码

在通常情况下,都是使用 interface 定义类型,在极少情况下会使用 type。

泛型是什么?有什么应用场景

  • 泛型是什么

泛型的本质是参数化类型,通俗的将就是所操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法的创建中,分别成为泛型类,泛型接口、泛型方法。

TypeScript 中不建议使用 any 类型,不能保证类型安全,调试时缺乏完整的信息。

  • 应用场景

TypeScript可以使用泛型来创建可重用的组件。支持当前数据类型,同时也能支持未来的数据类型。扩展灵活。可以在编译时发现你的类型错误,从而保证了类型安全。

我们还可以在接口中使用泛型。

后端提供了一些接口,用以返回一些数据,依据返回的数据格式定义如下接口:

interface IResponseData {
    code: number;
    message?: string;
        data: any; 
}
复制代码

根据接口,我们封装对应的一些方法。

function getData(url: string) { 
    return fetch(url).then(res => {
        return res.json();
    }).then( (data: IResponseData) => {
        return data;
  });
}
复制代码

但是,该接口的 data 项的具体格式不确定,不同的接口会返回的数据是不一样的,当我们想根据具体当前请求的接口返回具体 data 格式的时候,就比较麻烦了,因为 getData 并不清楚你调用的具体接口是什么,对应的数据又会是什么样的。这个时候我们可以对 IResponseData 使用泛型.

interface IResponseData<T> {
    code: number;
    message?: string;
        data: T; 
}
function getData<U>(url: string) { 
    return fetch(url).then(res => {
            return res.json();
  }).then( (data: IResponseData<U>) => {
       return data;
  });
}
复制代码
文章分类
前端
文章标签