中金回顾

1.近来的前端趋势

大前端简介

  1. 前端的一个趋势就是大前端,大前端就是所有前端的统称,比如Android、iOS、web、Watch等。大前端最大的特点在于一次开发,同时适用于所有平台,开发者不用为一个APP需要做Android和iOS两种模式而担心。
  2. 大前端是web统一的时代,利用web不仅能开发出网站,更可以开发手机端web应用和移动端应用程序。
  3. 大前端的主要核心就是跨平台技术,有了跨平台技术,各个平台的差异性就抹平了,开发者只需要一套技术栈就可以开发出适用于多个平台的客户端。

跨平台方案

  1. H5+原生(Cordova、Ionic、微信小程序)

    • 优点: 由于h5代码只需要一次开发,就能同时在Android和iOS两个平台运行,可以减小开发成本。
    • 缺点: h5代码是运行在WebView中,对于大多数系统能力都没有访问权限,如无法访问文件系统、不能使用蓝牙等。
    • 注意:混合框架一般都会在原生代码中预先实现一些访问系统能力的API, 然后暴露给WebView以供JavaScript调用,这样一来,WebView就成为了JavaScript与原生API之间通信的桥梁,主要负责JavaScript与原生之间传递调用消息,而消息的传递必须遵守一个标准的协议,它规定了消息的格式与含义,我们把依赖于WebView的用于在JavaScript与原生之间通信并实现了某种消息传输协议的工具称之为WebView JavaScript Bridge, 简称 JsBridge,它也是混合开发框架的核心。
  2. JavaScript开发+原生渲染 (React Native、Weex、快应用)

    • 优点:

      • 采用Web开发技术栈,社区庞大、上手快、开发成本相对较低。
      • 原生渲染,性能相比H5提高很多。
      • 动态化较好,支持热更新。
    • 缺点:

    • 渲染时需要JavaScript和原生之间通信
    • JavaScript为脚本语言,执行时需要JIT,执行效率和AOT代码仍有差距。
    • 由于渲染依赖原生控件,不同平台的控件需要单独维护,并且当系统更新时,社区控件可能会滞后;除此之外,其控件系统也会受到原生UI系统限制。
  3. 自绘UI+原生(Flutter)

    介绍:通过在不同平台实现一个统一接口的渲染引擎来绘制UI,而不依赖系统原生控件,所以可以做到不同平台UI的一致性。注意,自绘引擎解决的是UI的跨平台问题,如果涉及其它系统能力调用,依然要涉及原生开发。

    • 优点:
    • 性能高;由于自绘引擎是直接调用系统API来绘制UI,所以性能和原生控件接近。
    • 灵活、组件库易维护、UI外观保真度和一致性高;由于UI渲染不依赖原生控件,也就不需要根据不同平台的控件单独维护一套组件库,所以代码容易维护。由于组件库是同一套代码、同一个渲染引擎,所以在不同平台,组件显示外观可以做到高保真和高一致性;另外,由于不依赖原生控件,也就不会受原生布局系统的限制,这样布局系统会非常灵活。

    • 缺点:

    • 动态性不足;为了保证UI绘制性能,自绘UI系统一般都会采用AOT模式编译其发布包,所以应用发布后,不能像Hybrid和RN那些使用JavaScript(JIT)作为开发语言的框架那样动态下发代码。

      Flutter

      Flutter 是 Google推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。开发者可以通过 Dart语言开发 App,一套代码同时运行在 iOS 和 Android平台。 Flutter提供了丰富的组件、接口,开发者可以很快地为 Flutter添加原生扩展。

      Flutter既不使用WebView,也不使用操作系统的原生控件。 相反,Flutter使用自己的高性能渲染引擎来绘制widget。这样不仅可以保证在Android和iOS上UI的一致性,而且也可以避免对原生控件依赖而带来的限制及高昂的维护成本。

      Flutter使用Skia作为其2D渲染引擎,Skia是Google的一个2D图形处理函数库,包含字型、坐标转换,以及点阵图都有高效能且简洁的表现,Skia是跨平台的,并提供了非常友好的API,目前Google Chrome浏览器和Android均采用Skia作为其绘图引擎,值得一提的是,由于Android系统已经内置了Skia,所以Flutter在打包APK(Android应用安装包)时,不需要再将Skia打入APK中,但iOS系统并未内置Skia,所以构建iPA时,也必须将Skia一起打包,这也是为什么Flutter APP的Android安装包比iOS安装包小的主要原因。

      但是Flutter也有不足之处,不支持动态下发代码和热更新。

  1. 增强版Web App(PWA)

    PWA不属于上述跨平台开发的某一种,它是一种理念,PWA 本质上是 Web App,借助一些新技术也具备了 Native App 的一些特性,比如离线能力、本地缓存、和通知推送,兼具 Web App 和 Native App 的优点,看起来更像一个原生App。PWA完全使用前端技术栈,不过它需要手机和浏览器的支持,目前支持ServiceWorker和Google Play Service的Android手机,以及搭载11.3以上的iOS手机可以使用PWA。由于国内手机厂商和浏览器厂商的统一性问题,PWA在国内发展不是很好,但是在国外并没有这些问题。

2.node中间件

一个中间件是一个用于处理客户端请求的函数。一个HTTP服务器中可能会使用到各种中间件。当接收到一个客户端请求时,首先将该请求提交给第一个中间件函数,每一个中间件函数内部封装一个next回调函数,在一个中间件函数内部可以判断是否调用next回调函数来处理该客户端请求。一个最简单的中间件的书写方法如下所示。

```js
function middleware(req,res,next){next()}
```

在Express框架中,使用应用程序实例对象的use方法来调用一个中间件,该方法的使用方式如下所示。

```js
app.use([path],function)
```

在use方法中,使用两个参数,其中path参数为可选参数,function参数为必须指定参数。path参数值为一个字符串,用于指定何种路径应用中间件,默认参数值为“/”。function参数值为一个函数,用于指定我们所要调用的中间件函数。

3.使用websocket要注意什么,如何保证有效传输

  • 心跳机制

     在使用websocket的过程中,有时候会遇到网络断开的情况,但是在网络断开的时候服务器端并没有触发onclose的事件。这样会有:服务器会继续向客户端发送多余的链接,并且这些数据还会丢失。所以就需要一种机制来检测客户端和服务端是否处于正常的链接状态。因此就有了websocket的心跳了。还有心跳,说明还活着,没有心跳说明已经挂掉了。
    

如果断开连接可以,重连,重连失败再进行轮询。

4.项目中困难的事

5.https怎么实现的,在哪一层加密的

  1. 证书的获取
  2. 客户端识别证书
  3. 客户端生成随机数,通过证书中的公钥按照约定的非对称加密算法进行加密,得到加密的随机数秘钥,并把加密后的随机数传输到服务端
  4. 服务端收到随机数秘钥和加密签名,先使用私钥将随机数按照约定的非对称解密算法进行解密,获取随机数,同时使用随机数按照约定的对称解密算法进行解密
  5. 服务端通过客户端传入的随机数构造对称加密算法,对返回结果内容进行加密后传输

    https只保证传输过程的安全。 https只有在证书验证的时候使用非对称加密,数据传输的时候使用对称加密。

6.原型链继承

function Cat(){ 
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';

7.前端工程化做了一些什么

8.webpack优化除了一些普通的,还有啥

  • webpack打包优化

      1. 优化Loader:对于Loader,影响打包效率的是它的属性Babel.Babel会将代码转为字符串 生成AST,然后对AST继续进行转变最后生成新的代码,项目越大,转换代码越多,效率就越低。
    • 优化Loader的文件搜索范围(只在src文件夹下查找,不去找node_module路径)

 ```js

module.exports = { module:{ rules:[ { //js文件才使用babel test:/.js$/, loader:'babel-loader', //只在src文件夹下查找 include:[resolve('src')], //不会去查找的路径 exclude:/node_modules/ } ] } }

 ```
  • 把Babel编译过的文件缓存起来

    loader: 'babel-loader?cacheDirectory=ture'
    
    1. HappyPack

因为Node是单线程运行的,所以Webpack在打包的过程中也是单线程的,特别是在执行Loader的时候,这样会导致等待的情况。HappyPack可以将Loader的同步执行转换为并行的

module:{
        loader:[
           {
                //js文件才使用babel
                test:/\.js$/,
                //只在src文件夹下查找
                include:[resolve('src')],
                exclude:/node_modules/,
                //id后面的内容对应下面
                loader:'happypack/loader?id=happypack'
           }
        ]
    },
    plugins:[
      new HappyPack({
        id:'happypack',
        loaders:['babel-loader?cacheDirectory'],
        //开启4个线程
        threads:4
      })
    ]
    1. DllPlugin

      DllPlugin可以将特定的类库提前打包然后引入。这种方式可以极大的减少打包类库的次数,只有当类库更新版本才有需要重新打包,并且也实现了将公共代码抽离成单独文件的优化方案。

//单独配置在一个文件里
    //webpack.dll.conf.js
    const path = require('path')
    const webpack = require('webpack')
    module.exports = {
        entry:{
            //想统一打包的库
            vendor:['react']
        },
        output:{
            path:path.join(__dirname,'dist'),
            filename:'[name].dll.js',
            library:'[name]-[hash]'
        },
        plugins:[
          new webpack.DllPlugin({
            //name必须和output.library一致
            name:'[name]-[hash]',
            //该属性需要与DllReferencePlugin中一致
            context:__dirname,
            path:path.join(__dirname,'dist','[name]-mainfest.json')
          })
        ]
    }

然后需要执行这个配置文件生成依赖文件,接下来需要使用DllReferencePlugin将依赖文件引入项目中

//webpack.conf.js
   module.exports={
    //...省略其他配置
    plugins: [
      new webpack.DllReferencePlugin({
        context: __dirname,
        mainfest:require('./dist/vendor-mainfest.json')
      })
    ]
   }
`
  • 按需加载

  • Tree Shaking

  • HMR 模块热替换

    全称Hot Module Replacement 热模块替换,作用是当一个模块发生改变时,之后只会打包这样一个模块(而不是打包所有模块),极大提升构建速度。

  • 压缩代码

9.首屏加载时间除了浏览器那里,还能怎么看

10.对象映射

11.flutter

12.最近在看什么书

13.tcp udp区别

14.cors(跨域资源共享) 怎么弄? cookie怎么办呢

浏览器发送跨域请求,会在请求头中增加Origin属性。Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。

服务端配置字段:

  • Access-Control-Allow-Origin:该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

  • Access-Control-Allow-Credentials:该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

  • Access-Control-Expose-Headers:该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。

如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段。

Access-Control-Allow-Credentials: true

另一方面,开发者必须在AJAX请求中打开withCredentials属性。

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

需要注意的是,如果要发送Cookie,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名。同时,Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie也无法读取服务器域名下的Cookie。

CORS 对比 JSONP

都能解决 Ajax直接请求普通文件存在跨域无权限访问的问题

  1. JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求
  2. 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理
  3. JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS

15. Object.create()跟new的区别

Object.create()方法是ECMAScript5中新增的,用来规范化原型式继承的。

Object.create()方法接受两个参数:Object.create(obj,propertiesObject)。

new Object()方法的实质是,使用引用类型Object的构造函数创建了一个新的实例,这个实例拥有Object默认的方法如toString、toLocaleString等。

16. for in 与 for of区别

  1. for in只能获得对象的键名,不能获得键值。for of 允许遍历获得键值。
  2. 对于普通对象,没有部署原生的 iterator 接口,直接使用 for...of 会报错。
  3. for...in 循环不仅遍历数字键名,还会遍历手动添加的其它键,甚至包括原型链上的键。for...of 则不会这样。

总之,for...in 循环主要是为了遍历对象而生,不适用于遍历数组。

for...of 循环可以用来遍历数组、类数组对象,字符串、Set、Map 以及 Generator 对象。

prototype 与 proto

  • prototype:每一个函数在创建之后都会拥有一个名为prototype的属性,这个属性指向函数的原型对象

  • proto:对象具有属性proto,可称为隐式原型,指向构造该对象的构造函数的原型,这也保证了实例能够访问在构造函数原型中定义的属性和方法。