标签:ttl 网络 message 原因 包含 capture 了解 hello 精准
event loop
Promise
内部的语句是立即执行的,以上所说的微任务 Promise
指的是 Promise.then
function p(){
return new Promise(resolve => {
console.log(‘resolve‘)
resolve()
})
}
p().then(() => {
console.log(‘hello‘)
})
console.log(‘hi‘)
// ‘resolve‘ ‘hi‘ ‘hello‘
let a = 0
let b = async () => {
a = a + await 10
console.log(‘2‘, a)
}
b()
a++
console.log(‘1‘, a)
// -> ‘1‘ 1
// -> ‘2‘ 10
setTimeinterval
和 setTimeout
准确吗,原因?由于 javascript 的 event loop
机制,setTimeinterval
和 setTimeout
需要在主线程任务和微任务结束后执行,这就意味着如果主线程的处理时间超出了设置的时间时这两种方法肯定是不准确的
setTimeout
,setInterval
在 event loop
的宏任务中,当主线程结束时才会按照任务队列加载
requestAnimationFrame
在主线程中执行,所以更加准确,以1秒钟60次(大约每16.7毫秒一次)的频率执行
function setInterval(callback, interval) {
let timer
const now = Date.now
let startTime = now()
let endTime = startTime
const loop = () => {
timer = window.requestAnimationFrame(loop)
endTime = now()
if (endTime - startTime >= interval) {
startTime = endTime = now()
callback(timer)
}
}
timer = window.requestAnimationFrame(loop)
return timer
}
let a = 0
setInterval(timer => {
console.log(1)
a++
if (a === 3) cancelAnimationFrame(timer)
}, 1000)
在 javascript 中,一切皆对象,而每个对象都会有一个 __proto__
属性, __proto__
指向实例化该对象的构造函数的 prototype
,而该构造函数的 __proto__
又指向它的构造函数的 __proto__
如此往复向下,直到底层为 null
时停止,当调用一个对象的方法时,javascript 会顺着这条线寻找该方法。
prototype
,class
使用 ==
时,如果两边值的类型不同会触发类型转换,所以会出现 Boolean(‘1‘ == 1) === true
,使用 ===
时则不会
函数 A 内部有一个函数 B,函数 B 可以访问到函数 A 中的变量,那么函数 B 就是闭包
for (var i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i)
}, i * 1000)
}
// 6个6
Function.prototype.myCall = function(context) {
if (typeof this !== ‘function‘) {
throw new TypeError(‘Error‘)
}
context = context || window
context.fn = this
const args = [...arguments].slice(1)
const result = context.fn(...args)
delete context.fn
return result
}
Function.prototype.myApply = function(context) {
if (typeof this !== ‘function‘) {
throw new TypeError(‘Error‘)
}
context = context || window
context.fn = this
let result
if (arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result
}
Function.prototype.myBind = function (context) {
if (typeof this !== ‘function‘) {
throw new TypeError(‘Error‘)
}
const _this = this
const args = [...arguments].slice(1)
// 返回一个函数
return function F() {
if (this instanceof F) {
return new _this(...args, ...arguments)
}
return _this.apply(context, args.concat(...arguments))
}
}
function create() {
let obj = {}
let Con = [].shift.call(arguments)
obj.__proto__ = Con.prototype
let result = Con.apply(obj, arguments)
return result instanceof Object ? result : obj
}
instanceof
可以正确的判断对象的类型,因为内部机制是通过判断对象的原型链中是不是能找到类型的 prototype
。
function myInstanceof(left, right) {
let prototype = right.prototype
left = left.__proto__
while (true) {
if (left === null || left === undefined)
return false
if (prototype === left)
return true
left = left.__proto__
}
}
冒泡:由小及大,从子元素事件发出,向父元素,父元素的父元素...直至 html
为止
捕获:由大及小,从父元素发出,向其下的子元素...直至最小的元素为止
使用 element.addEventListener(type,listener,options)
,在 options.capture
设置使用冒泡还是捕获,默认冒泡
一般使用在有大量或者是动态渲染的html元素需要绑定事件时,以达到提高性能或动态绑定的目的。
将事件绑定在 html 元素的父元素上,通过事件流的冒泡属性,在父元素中获取到点击的子元素,加以判断后实行相应的事件。
当协议、域名或者端口有一个不同即是跨域,浏览器会拦截 ajax 请求,目的是为了防止 CSRF 攻击。简单点说,CSRF 攻击是利用用户的登录态发起恶意请求。
浏览器拦截的是读取内容的请求,所以通过表单等方式的请求是不会被拦截的
仅在同域名和同域名不同文件夹下两种情况时不存在跨域,其余皆为跨域
<script>
标签没有跨域限制的漏洞。通过 <script>
标签指向一个需要访问的地址并提供一个回调函数来接收数据当需要通讯时。function jsonp(url, jsonpCallback, success) {
let script = document.createElement(‘script‘)
script.src = url
script.async = true
script.type = ‘text/javascript‘
window[jsonpCallback] = function(data) {
success && success(data)
}
document.body.appendChild(script)
}
jsonp(‘http://xxx‘, ‘callback‘, function(value) {
console.log(value)
})
该方式只能用于二级域名相同的情况下,比如 a.test.com 和 b.test.com 适用于该方式。
只需要给页面添加 document.domain = ‘test.com‘ 表示二级域名都相同就可以实现跨域
主要用于页面和其下的 iframe 之间的通讯
async
属性为 defer
重绘仅改变节点的外观,不影响布局,如改变节点的 color 属性
回流指节点的大小或页面的布局发生改变
回流必定会发生重绘,重绘不一定会引发回流
header包含:
请求的方法(get、post、put..) 协议(http、https、ftp、sftp…) 目标url(具体的请求路径已经文件名) 一些必要信息(缓存、cookie之类)
body包含:
请求的内容
script
标签时会等待其中 js
代码执行完成后继续执行上述步骤(会造成阻塞)// ES5
function Animal() {
this.type = ‘animal‘
this.eat = function(){}
}
function Cat() {
Animal.call(this)
this.name = ‘cat‘
}
function inherits(Child, Parent) {
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
// ES6
class Fruit{
constructor(){}
}
class Apple extends Fruit{
constructor(){
super()
}
}
先明确:虚拟 dom (框架封装的)不一定比 原生 dom 快 参考
好处:
简化dom操作,让数据与dom之间的关系更直观更简单
用于加载某些资源文件。 因为webpack 本身只能打包commonjs规范的js文件,对于其他资源例如 css,图片,或者其他的语法集,比如 jsx, coffee,是没有办法加载的。 这就需要对应的loader将资源转化,加载进来。从字面意思也能看出,loader是用于加载的,它作用于一个个文件上。
用于扩展webpack的功能。它直接作用于 webpack,扩展了它的功能。当然loader也时变相的扩展了 webpack ,但是它只专注于转化文件(transform)这一个领域。而plugin的功能更加的丰富,而不仅局限于资源的加载。
通常浏览器缓存策略分为两种:强缓存和协商缓存,并且缓存策略都是通过设置 HTTP Header 来实现的。
强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control 。强缓存表示在缓存期间不需要请求,state code 为 200。
如果缓存过期了,就需要发起请求验证资源是否有更新。协商缓存可以通过设置两种 HTTP Header 实现:Last-Modified 和 ETag 。
Web 前端 中高难度问题(希望看完之后的你可以拿到Offer^v^)
标签:ttl 网络 message 原因 包含 capture 了解 hello 精准
原文地址:https://www.cnblogs.com/sweet-ice/p/10534354.html