zoukankan      html  css  js  c++  java
  • 面试十题(3)

    cookie

    登录后服务端生成的sessionid,并在http请求里返回到客户端,同时服务端保存sessionid,以后客户端的每次http请求都带上cookie(sessionid),服务端会获取cookie(sessionid)然后验证用户的身份。所以拿到cookie就拿到了sessionid,就可验证通过。同时浏览器会自动携带cookie;

    token

    同样是登录后服务端返回一个token,客户端保存起来,在以后http请求里手动的加入到请求头里,服务端根据token 进行身份的校验。浏览器不会自动携带token。

    CSRF 跨站点请求伪造

    通过浏览器会自动携带同域cookie的特点。cookie的传递流程是用户在访问站点时,服务器端生成cookie,发送给浏览器端储存,当下次再访问时浏览器会将该网站的cookie发回给服务器端。 而浏览器不会自动携带 token,所以不会劫持 token。

    XSS 跨域脚本攻击。

    跨站脚本工攻击是指通过存在安全漏洞的Web网站注册用户的浏览器内运行非法的HTML标签或者JavaScript进行的一种攻击。 就是说,cookie和token都可能被拿到,所以都废了。

    2. 合并两个数组

    请把两个数组 ['A1', 'A2', 'B1', 'B2', 'C1', 'C2', 'D1', 'D2'] 和 ['A', 'B', 'C', 'D'],合并 为 ['A1', 'A2', 'A', 'B1', 'B2', 'B', 'C1', 'C2', 'C', 'D1', 'D2', 'D']。

    let a1 =  ['A1', 'A2', 'B1', 'B2', 'C1', 'C2', 'D1', 'D2']
    let a2 = ['A', 'B', 'C', 'D'].map((item) => {
      return item + 3
    })
    
    let a3 = [...a1, ...a2].sort().map((item) => {
      if(item.includes('3')){
        return item.split('')[0]
      }
      return item
    })
    

    3. 改造下面的代码,使之输出0-9,写出你能想到的所有解法。

    for (var i = 0; i < 10; i++) {
        setTimeout(() => {
            console.log(i)
        }, 1000)
    }
    

    解法一:

    // 块级作用域
    for (let i = 0; i < 10; i++){
        setTimeout(() => {
            console.log(i);
        }, 1000)
    }
    

    解法二:

    // 自执行函数,把当前的i传递给自执行函数,构建块级作用域
    for (var i = 0; i < 10; i++){
       (i => {
           setTimeout(() => {
               console.log(i)
           }, 1000)
       })(i)
    }
    

    解法三:

    // 利用 setTimeout 函数的第三个参数,会作为回调函数的第一个参数传入
    // 同步
    // var a = 9
    // setTimeout(a++, 3000)
    // console.log(a)
    // 异步
    // var a = 9
    // setTimeout('a++', 3000)
    // console.log(a)
    
    // 同步。setTimeout第一个参数自执行函数
    for (var i = 0; i< 10; i++){
      setTimeout(((i) => {
        console.log(i);
        })(i), 1000)
    }
    // setTimeout第三个参数会作为setTimeout回调函数的参数
    for (var i = 0; i < 10; i++) {
      setTimeout(console.log, 1000, i)
    }
    

    解法四:

    // 利用try catch
    for(var i = 0; i < 10; i++){ 
      try{
        throw i;
      }catch(i){
        setTimeout(() => { 
            console.log(i)
        }, 1000)
      }
    } 
    

    解法五:

    // promise
    for (var i = 0; i < 10; i++) {
        timeoutPromise(i);
    }
    function timeoutPromise(i) {
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log(i);
                resolve();
            }, 1000);
        });
    }
    

    解法六:

    // Generator函数
    for (var i = 0; i < 10; i++) {
        timeoutGenerator(i).next();
    }
    function* timeoutGenerator (i) {
        yield setTimeout(() => {
            console.log(i);
        }, 1000);
    }
    

    解法七:

    // async await
    async function init () {
        for (var i = 0; i < 10; i++) {
            await timeoutPromise(i);
        }    
    }
    function timeoutPromise (i) {
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log(i);
                resolve();
            }, 1000);   
        });
    }
    init();
    // 1秒打印1

    解法八:

    // apply call bind
    // 区别apply和call都是同步执行,bind是异步执行
    // apply 参数是数组形式
    
    // ① apply 同步
    for (var i = 0; i < 10; i++) {
        setTimeout(console.log.apply(null, [i]), 1000)
    }
    
    // ② call  同步
    for (var i = 0; i < 10; i++) {
        setTimeout(console.log.call(null, i), 1000)
    }
    
    // 异步
    for (var i = 0; i < 10; i++) {
        setTimeout(console.log.bind(null, i), 1000)
    }
    
    
    

    4. Virtual DOM 真的比操作原生 DOM 快吗?谈谈你的 想法。

    • 没有任何框架可以比纯手动的优化 DOM 操作更快,因为框架的 DOM 操作层需要应对任何上层 API 可能产生的操作,它的实现必须是普适的。
    • Virtual DOM 真正的价值从来都不是性能,而是它:
      1. 为函数式的 UI 编程方式打开了大门;
      1. 可以渲染到 DOM 以外的 backend,比如 ReactNative。

    参考链接

    5. 下面代码打印什么,为什么?

    var b = 10;
    (function b() {
        b = 20
        console.log(b)
        console.log(window.b)
    })()
    
    // ƒ b() {
    //    b = 20
    //    console.log(b)
    //    console.log(window.b)
    
    // 10
    }
    
    • 解析:
    
    var b = 10;
    (function b() {
       // 内部作用域,会先去查找是有已有变量b的声明,有就直接赋值20,确实有了呀。发现了具名函数 function b(){},拿此b做赋值;
       // IIFE的函数无法进行赋值(内部机制,类似const定义的常量),所以无效。
      // (这里说的“内部机制”,想搞清楚,需要去查阅一些资料,弄明白IIFE在JS引擎的工作方式,堆栈存储IIFE的方式等)
        b = 20;
        console.log(b); // [Function b]
        console.log(window.b); // 10,不是20
    })();
    

    所以严格模式下能看到错误:Uncaught TypeError: Assignment to constant variable

    var b = 10;
    (function b() {
      'use strict'
      b = 20;
      console.log(b)
    })()
    // "Uncaught TypeError: Assignment to constant variable."
    

    其他情况例子:

    // 有window
    
    var b = 10;
    (function b() {
        window.b = 20; 
        console.log(b); // function
        console.log(window.b); // 20是必然的
    })();
    
    // 有var
    
    var b = 10;
    (function b() {
        var b = 20; // IIFE内部变量
        console.log(b); // 20
       console.log(window.b); // 10 
    })();
    

    6. 浏览器缓存读取规则

    参考链接

    7. 聊聊 Vue 的双向数据绑定,Model 如何改变 View, View 又是如何改变 Model 的

    • 待整理! link

    8. 使用迭代的方式实现 flatten 函数。

    let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]];

    • 递归方法(ES6)
    const flatten = (array) =>
      array.reduce(
        (acc, cur) =>
          Array.isArray(cur) ? [...acc, ...flatten(cur)] : [...acc, cur],
        []
      );
    
    • some方法
    // some() 不会对空数组进行检测。
    // some() 不会改变原始数组。
    const flatten = function (arr) {
      while (arr.some((item) => Array.isArray(item))) {
        arr = [].concat(...arr);
      }
      return arr;
    };
    
    • 先转成字符串,再转成数组
    arr.join(',').split(',').map(item => Number(item))
    // 或者
    arr.toString().split(',').map(item => Number(item))
    
    • reduce用法。

    9. 为什么 Vuex 的 mutation 和 Redux 的 reducer 中 不能做异步操作?

    • Mutation必须是同步函数。 vuex和redux都是一种状态管理机制。然后他们会有自己的state(状态)和修改state的方法,修改state的方法涉及到同步和异步,vuex的处理方式是同步在mutation里面,异步在actions里面,然后redux的同步就是reducer,异步更多的是用户自己去通过中间件的方式去实现

    10. 下面代码中 a 在什么情况下会打印 1?

    var a = ???
    if (a == 1 && a == 2 && a == 3) {
        console.log(1)
    }
    // 问a等于什么时候 打印1
    // 至少两种方法
    
    // 考察对象和基础数据比较,先执行toString(),如果还不是普通数据,再执行valueOf()
    // ①
    var a = {
        i: 1,
        toString() {
            return a.i++
        }
    }
    // console.log(a == 1 && a == 2 && a == 3) // true
    
    // ②
    var a  = [1,2,3]
    a.toString = a.shift
    // console.log(a == 1 && a == 2 && a == 3) // true
  • 相关阅读:
    01、启动优先和安全设置
    5、bam格式转为bigwig格式
    1、蛋白质二级结构预测方法
    12、IGV-Integrative Genomics Viewer
    docker-compose 工具安装
    docker-compose.yml 语法说明
    docker 镜像和容器的批量清理
    rancher 笔记 之 rancher应用中心
    golang 学习笔记
    docker registry 搭建
  • 原文地址:https://www.cnblogs.com/jialuchun/p/15207510.html
Copyright © 2011-2022 走看看