1、http 和 https 都有哪些区别?
HTTP(超文本传输协议)和 HTTPS(超文本传输安全协议)都是用于在网络上传输数据的协议,但它们之间存在一些关键区别。主要的区别在于安全性和数据传输方式。
HTTP和HTTPS的区别主要有以下几点:
- HTTPS需要申请证书,一般需要付费,而HTTP不需要。
- HTTP是明文传输,不安全,HTTPS是加密传输,安全。
- HTTP和HTTPS使用不同的端口,HTTP是80端口,HTTPS是443端口
- HTTPS比HTTP更耗费服务器资源,响应速度比HTTP慢
- HTTPS对搜索排名有一定的提升作用
2、构造函数中 new 关键字都⼲了什么事情?
-
创建一个新的空对象:
new
关键字首先会创建一个新的空对象。这个对象将成为构造函数内部this
的值,并且最终被作为构造函数的实例返回。 -
设置原型链接:新创建的空对象的原型(
[[Prototype]]
)将被设置为构造函数的prototype
属性所指向的对象。这意味着新创建的对象将能够访问在构造函数原型上定义的所有属性和方法。 -
绑定
this
:在构造函数内部,this
将被绑定到新创建的空对象。这使得在构造函数中通过this
定义的属性和方法会被添加到新创建的对象上。 -
执行构造函数中的代码:构造函数中的代码将被执行,可以使用
this
来设置新对象的属性和方法。 -
返回新对象:如果构造函数没有显式返回对象或其他非基本类型值,
new
关键字会自动返回新创建的对象。如果构造函数显式返回了一个对象或其他非基本类型值,那么new
关键字会返回这个值,而不是新创建的对象。这个一个简单的构造函数示例:
function Person(name, age) {
this.name = name;
this.age = age;
this.sayHello = function() {
console.log('Hello, my name is ' + this.name + ' and I am ' + this.age + ' years old.');
};
}
const john = new Person('John', 30);
john.sayHello(); // 输出 "Hello, my name is John and I am 30 years old."
我们定义了一个名为 Person
的构造函数,接受 name
和 age
两个参数。使用 new
关键字创建 Person
的实例时,会执行上述操作,最终返回一个新的 Person
对象。
3、什么是防抖和节流?⼿写对应代码?
防抖和节流都是优化高频率触发的事件的方法,它们可以减少事件的处理次数,提高性能和用户体验。
防抖(debounce)是指在某个时间段内,事件处理函数只执行最后一次触发的事件,而忽略在该时间段内其他被触发的事件。
手写防抖的代码如下:
// 防抖
function debounce(fn, delay) {
let timer = null; // 定义一个定时器变量
return function() {
let context = this; // 保存当前函数的上下文
let args = arguments; // 保存当前函数的参数
clearTimeout(timer); // 清除之前的定时器
timer = setTimeout(function() { // 设置一个新的定时器
fn.apply(context, args); // 在延迟时间后执行函数
}, delay);
}
}
这里的 debounce
函数接受两个参数:被包装的函数 func
和防抖延迟时间 delay
。当被包装的函数被调用时,会在 delay
毫秒后执行。如果在 delay
毫秒内再次调用了被包装的函数,则计时器会被重置,重新开始计时。
节流(throttle)是指在某个时间段内,事件处理函数最多执行一次,且是第一次,而忽略在该时间段内其他被触发的事件。
// 节流
function throttle(fn, delay) {
let timer = null; // 定义一个定时器变量
return function() {
let context = this; // 保存当前函数的上下文
let args = arguments; // 保存当前函数的参数
if (!timer) { // 如果没有定时器
timer = setTimeout(function() { // 设置一个新的定时器
fn.apply(context, args); // 立即执行函数
timer = null; // 清空定时器变量
}, delay);
}
}
}
这里的 throttle
函数接受两个参数:被包装的函数 func
和节流时间 delay
。当被包装的函数被调用时,如果上一次执行到现在的时间小于 delay
毫秒,则函数不会被执行。如果上一次执行到现在的时间大于等于 delay
毫秒,则函数会被执行,并且计时器会被重置,重新开始计时。
4、谈谈什么是事件队列?什么是微任务?什么是宏任务?
事件队列是一种数据结构,用来存放异步事件的回调函数。当异步事件完成后它的回调函数会被放入事件队列中,等待主线程的执行。
微任务是一些需要在当前任务结束后立即执行的异步事件,比如Promise.then0、async/await、MutationObserver等。微任务会被放入一个单独的微事件队列中,在当前任务执行完毕后,主线程会立即清空微事件队列,执行所有的微任务回调函数。
宏任务是一些需要在下一个任务开始前执行的异步事件,比如setTimeout0.setlnterval0、DOM事件等。宏任务会被放入一个或多个宏事件队列中,在每次事件循环中,主线程会从宏事件队列中取出一个事件回调函数,放入执行栈中执行。在执行完一个宏任务后,主线程会检查微事件队列,如果有微任务,就先执行微任务,再执行下一个宏任务。
当异步任务执行完毕后,会将其添加到对应的任务队列中。宏任务队列在微任务队列之前执行,而微任务队列会在下一次事件循环的开始时执行,确保微任务队列中的任务能够在页面渲染之前得到执行。
以下是一段示例代码,演示了宏任务和微任务的执行顺序:
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
console.log('script end');
输出结果为:
script start
script end
promise1
promise2
setTimeout