js答题

249 阅读3分钟

1.什么是事件冒泡和事件捕获,区别是什么?

冒泡 从下到上,点击子元素事件,先响应当前元素事件,再一层一层往上响应。
捕获 从上到下。点击当前元素事件,先响应父元素,最后响应当前元素事件。
解决办法 event.stopPropagation()

2.什么是跨域,如何处理跨域

http://www.taobao.com/index.html 调用 http://www.tencent.com/server.php (taobao/tencent 跨域)主域名不同

http://www.taobao.com/index.html 调用 http://zzz.taobao.com/server.php (www/zzz 跨域)子域名不同

http://www.taobao.com:8080/index.html 调用 http://www.taobao.com:8088/server.php (8080/8088,跨域)端口不同

http://www.123.com/index.html 调用 https://www.123.com/server.php (协议不同:http/https,跨域)

请注意:localhost 和 127.0.0.1 虽然都指向本机,但也属于跨域。
解决办法: 1.jsonp 2.后台设置允许跨域Access-Control-Allow-Origin

3.什么是节流与防抖,如何实现

节流:多次触发,固定时间,执行固定次数。举例,5秒内多次触发,1秒只执行一次。就会执行5次。
防抖:多次触发,只执行最后一次。举例,5秒内多次触发,只会执行最后一次事件。
解决办法,其实就是个典型的'闭包'应用。
// 节流 放到带浏览器默认滚动的页面测试,一直滚动页面。1秒内只会执行一次。
function test(fn, t) {
  let timer = false;
  return () => {
    console.log('滚动触发中');
    if (timer) return;
    timer = setTimeout(() => {
      fn();
      timer = false; // 置空操作
    }, t);
  };
}
window.addEventListener('scroll',test(() => {console.log('我一秒只会执行一次');}, 1000),false);
// 防抖
function test(fn, t) {
  let timer = null;
  return () => {
    if (timer) clearTimeout(timer)
      timer = setTimeout(() => {
        fn();
      }, t);
  };
}
window.addEventListener('scroll',test(() => {console.log('你再怎么滚我都不出来,除非你不滚动了,一秒之后我就乖乖的出来了');}, 1000),false);

4.浏览器缓存

Cookie: 4k太小,不安全
localStorage: 5M, 不会传输给后台。长期存在。
sessionStorage: 5M, 不会传输给后台。会话级别,关闭页面就清空了。

5.从浏览器输入url后,发生了什么

6.HTTPS为什么让数据传输更安全

谈到HTTPS, 就不得不谈到与之相对的HTTP。HTTP的特性是明文传输,因此在传输的每一个环节,数据都有可能被第三方窃取或者篡改,具体来说,HTTP 数据经过 TCP 层,然后经过WIFI路由器、运营商和目标服务器,这些环节中都可能被中间人拿到数据并进行篡改,也就是我们常说的中间人攻击。

为了防范这样一类攻击,我们不得已要引入新的加密方案,即 HTTPS。

HTTPS并不是一个新的协议, 而是一个加强版的HTTP。其原理是在HTTP和TCP之间建立了一个中间层,当HTTP和TCP通信时并不是像以前那样直接通信,直接经过了一个中间层进行加密,将加密后的数据包传给TCP, 响应的,TCP必须将数据包解密,才能传给上面的HTTP。这个中间层也叫安全层。安全层的核心就是对数据加解密。

7. 手写call apply bind

      Function.prototype.myAplly = function(...arr) {
        let fn = '_new' + Math.random() * 10000;
        arr[0][fn] = this;
        let params = arr.slice(1);
        params = params.constructor === Array ? params[0] : params;
        arr[0][fn](...params);
        delete arr[0][fn];
      };
      Function.prototype.myCall = function(...arr) {
        this.myAplly(arr[0], arr.slice(1));
      };
      Function.prototype.myBind = function(...arr) {
        let that = this;
        return function(params = []) {
          return that.myAplly(arr[0], arr.slice(1).concat(params));
        };
      };

8. 手动实现深拷贝

    mycapy(data) {
      let arr = data.constructor === Object ? {} : [];
      let keys = Object.keys(data);
      keys.forEach((r) => {
        arr[r] = [Array, Object].includes(data[r].constructor) ? this.mycapy(data[r]) : data[r];
      });
      return arr;
    }

9. 冒泡排序

    mySort(arr) {
      let len = arr.length;
      for (let i = len; i > 1; i--) {
        for (let n = 0; n < i - 1; n++) {
          if (arr[n] > arr[n + 1]) {
            [arr[n], arr[n + 1]] = [arr[n + 1], arr[n]];
          }
        }
      }
      return arr;
    }

10.选择排序

    mySort(arr) {
      let len = arr.length;
      for (let i = 0; i < len - 1; i++) {
        for (let n = i; n < len; n++) {
          if (arr[n] < arr[i]) {
            [arr[n], arr[i]] = [arr[i], arr[n]];
          }
        }
      }
      return arr;
    }

11.插入排序

    mySort(arr) {
      let len = arr.length;
      for (let i = 1; i < len; i++) {
        for (let n = i; n > 0; n--) {
          if (arr[n] >= arr[n - 1]) break;
          [arr[n], arr[n - 1]] = [arr[n - 1], arr[n]];
        }
      }
      return arr;
    }

12. 快速排序 (和sort速度差不多)

      if (arr.length <= 1) return arr;
      let i = parseInt(arr.length / 2);
      let [num, left, right] = [arr.splice(i, 1)[0], [], []];
      for (let n = 0; n < arr.length; n++) {
        arr[n] < num ? left.push(arr[n]) : right.push(arr[n]);
      }
      let _left = this.mySort4(left);
      let _right = this.mySort4(right);
      return _left.concat([num], _right);