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);