关于前端:问题集合2

42次阅读

共计 5733 个字符,预计需要花费 15 分钟才能阅读完成。

问题 1

requestAnimationFramesetTimeout 比照劣势

  • 当页面暗藏或者最小化时,setTimeout 依然在后盾执行动画,此时页面不可见或者是不可用状态,动画刷新没有意义,而言节约 CPU。
  • rAF 不一样,当页面解决未激活的状态时,该页面的屏幕绘制工作也会被零碎暂停,因而跟着零碎步调走的 rAF 也会进行渲染,当页面被激活时,动画就从上次停留的中央继续执行,无效节俭了 CPU 开销。

标准中仿佛是这么去定义的:
在从新渲染前调用。
很可能在宏工作之后不去调用
与节流比照
长处

  1. 动画放弃 60fps(每一帧 16 ms),浏览器外部决定渲染的最佳时机
  2. 简洁规范的 API,前期保护成本低

毛病

  1. 动画的开始 / 勾销须要开发者本人管制,不像‘.debounce’或‘.throttle’由函数外部解决。
  2. 浏览器标签未激活时,所有都不会执行。
  3. 只管所有的古代浏览器都反对 rAF,IE9,Opera Mini 和 老的 Android 还是须要打补丁。
  4. Node.js 不反对,无奈在服务器端用于文件系统事件。

问题 2 DNS 解析

  1. 首先查看是否有对应的域名缓存,有的话间接用缓存的 ip 拜访
  2. 如果缓存中没有,则去查找 hosts 文件,个别在 c:\windows\system32\drivers\etc\hosts
  3. 如果 hosts 文件里没找到想解析的域名,则将域名发往本人配置的 dns 服务器,也叫本地 dns 服务器ipconfig/all
  4. 如果本地 dns 服务器有相应域名的记录,则返回记录。
  5. 如果电脑本人的服务器没有记录,会去找根服务器。根服务器寰球只有 13 组,会去找其中之一, 找了根服务器后,根服务器会依据申请的域名,返回对应的“顶级域名服务器”
  6. 顶级域服务器收到申请,会返回二级域服务器的地址
  7. 以此类推,最终会发到负责锁查问域名的,最准确的那台 dns,能够失去查问后果
  8. 本地 dns 服务器,把最终的解析后果,返回给客户端。

问题 3 XSS CSRF

XSS 是指黑客往 HTML 文件中或者 DOM 中注入歹意脚本,从而在用户浏览页面时利用注入的歹意脚本对用户施行攻打的一种伎俩。
注入歹意脚本能够实现这些事件:

  1. 窃取 Cookie
  2. 监听用户行为,比方输出账号密码后之间发给黑客服务器
  3. 在网页中生成浮窗广告
  4. 批改 DOM 伪造登入表单

个别的状况下,XSS 攻打有三种实现形式

  • 存储型 XSS 攻打
  • 反射型 XSS 攻打
  • 基于 DOM 的 XSS 攻打

阻止 XSS 攻打的策略
对输出脚本进行过滤或转码
利用 CSP,该安全策略的实现基于一个称作 Content-Security-Policy的 HTTP 首部。

  • 限度加载其余域下的资源文件,这样即便黑客插入了一个 JavaScript 文件,这个 JavaScript 文件也是无奈被加载的;
  • 禁止向第三方域提交数据,这样用户数据也不会外泄;
  • 提供上报机制,能帮忙咱们及时发现 XSS 攻打。禁止执行内联脚本和未受权的脚本;

利用 HttpOnly。服务器能够将某些 Cookie 设置为 HttpOnly 标记,HttpOnly 是服务器通过 HTTP 响应头来设置

CSRF 英文全称是 Cross-site request forgery,所以又称为“跨站申请伪造”,是指黑客诱惑用户关上黑客的网站,在黑客的网站中,利用用户的登录状态发动的跨站申请。简略来讲,CSRF 攻打就是黑客利用了用户的登录状态,并通过第三方的站点来做一些好事。

防护策略

  1. 验证码机制,验证起源站点。次要通过 HTTP 申请头中的两个 Header,Origin 只蕴含域名信息,而 Referer 蕴含了具体的 URL 门路
    Origin Header
    Referer Header
  2. 利用 Cookie 的 SameSite 属性
    SameSite 能够设置为三个值,Strict、Lax 和 None。
    在 Strict 模式下,浏览器齐全禁止第三方申请携带 Cookie。
    在 Lax 模式只能在 get 办法提交表单况或者 a 标签发送 get 申请的状况下能够携带 Cookie
    在 None 模式下,Cookie 将在所有上下文中发送,即容许跨域发送
  3. CSRF Token

问题 4 开发一个 loader 和 Plugin

  1. loader 实质上就是一个函数,这个函数会在咱们在咱们加载一些文件时执行
  2. 开发 loader 函数,这个函数必须返回一个 buffer 或者 string
  3. 应用这个 loader,咱们应用 resolveLoader 配置项,指定 loader 查找文件门路,应用 loader 时候能够间接指定 loader 的名字
    resolveLoader: {
        // loader 门路查找程序从左往右
        modules: ['node_modules', './']
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                use: 'myLoader'
            }
        ]
    }

plugin 通常是在 webpack 在打包的某个工夫节点做一些操作,咱们应用 plugin 的时候,个别都是 new Plugin()这种模式应用,所以,首先应该明确的是,plugin 应该是一个类。
plugin 类外面须要实现一个 apply 办法,这个办法承受一个 compiler 作为参数,这个 compiler 是 webpack 实例.
比方

class DemoPlugin {constructor () {console.log('plugin init')
    }
    // compiler 是 webpack 实例
    apply (compiler) {// 一个新的编译 (compilation) 创立之后(同步)compiler.hooks.compile.tap('DemoPlugin', compilation => {console.log(compilation)
        })
        // 生成资源到 output 目录之前(异步)compiler.hooks.emit.tapAsync('DemoPlugin', (compilation, fn) => {console.log(compilation)
            compilation.assets['index.md'] = {
                // 文件内容
                source: function () {return 'this is a demo'},
                // 文件尺寸
                size: function () {return 10}
            }
            fn()})
    }
}

module.exports = DemoPlugin

问题 5

TCP/IP / 如何保障数据包传输的有序牢靠
对字节流分段并进行编号而后通过 ACK 回复超时重发 这两个机制来保障。

问题 6

粘包问题剖析与对策
TCP 粘包是指发送方发送的若干包数据到接管方接管时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。
粘包呈现起因
简略得说,在流传输中呈现,UDP 不会呈现粘包,因为它有音讯边界
粘包状况有两种,一种是粘在一起的包都是残缺的数据包,另一种状况是粘在一起的包有不残缺的包。
一种比拟周全的对策是:接管方创立一预处理线程,对接管到的数据包进行预处理,将粘连的包离开。试验证实这种办法是高效可行的。

问题 7

如何防止重绘或者重排?

  1. 集中扭转款式,不要一条一条地批改 DOM 的款式。
  2. 不要把 DOM 结点的属性值放在循环里当成循环里的变量。
  3. 为动画的 HTML 元件应用 fixed 或 absoult 的 position,那么批改他们的 CSS 是不会 reflow 的。
  4. 不应用 table 布局。因为可能很小的一个小改变会造成整个 table 的从新布局。
  5. 尽量只批改 position:absolute 或 fixed 元素,对其余元素影响不大
  6. 动画开始 GPU 减速,translate 应用 3D 变动
  7. 晋升为合成层

问题 8

  1. 浏览器一帧做了哪些事件
  2. 承受输出事件
  3. 执行事件回调
  4. 开始一帧
  5. 执行 RAF (RequestAnimationFrame)
  6. 页面布局,款式计算
  7. 渲染
  8. 执行 RIC (RequestIdelCallback)

问题 9

webpack 中 hash、fullhash、chunkhash 和 contenthash 的区别

  • hash– 编译产生,每次编译的时候都会实例化一个对象 compilation, 该对象掌控着从编译开始到编译完结文件,模块的加载,关闭,优化,分块,哈希,重建等等都是由其负责,此时的 hash 是由 compilation 来创立。跟整个我的项目的构建相干,只有我的项目里有文件更改,整个我的项目构建的 hash 值都会更改,并且全副文件都共用雷同的 hash 值
  • fullhash– 全量的 hash,是整个我的项目级别的。只有我的项目中有任何一个的文件内容产生变动,打包后所有文件的 hash 值都会产生扭转。
  • chunkhash– chunk, 每个入口文件都是一个 chunk,每个 chunk 是由入口文件与其依赖所形成,异步加载的文件也被视为是一个 chunk。hunkhash 是由每次编译模块,依据模块及其依赖模块形成 chunk 生成对应的 chunkhash, 文件未被扭转时,chunkhash 没变,浏览器能够利用缓存机制疾速加载,然而, 每个 chunk 都是有 css 与 js 组成, 也就是说当其中一个文件发生变化,这个 chunk 都会从新编译,比方配置成filename: 'bundle.[name].[chunkhash].js',一个 js 文件中引入了 css,批改后 js,css 文件的 hash 值都会变。
  • contenthash– 针对文件内容生成不同的 hash, 只有当文件内容发生变化此 hash 才会从新生成,利用 mini-css-extract-plugin 插件取提取出每个 chunk 的 css 文件,将 css 与 js 隔离开,而后将 css 更改,改变了哪个文件,哪个文件 hash 值才会变,比方配置成
new MiniCssExtractPlugin({
          // Options similar to the same options in webpackOptions.output
          // both options are optional
          filename: "css/[name].[contenthash].css",
          chunkFilename: "css/[name].[contenthash].css"
        })

问题 10

6.toString()转换报错 6. 的点有歧义,计算机不晓得是 get 符号还是小数点。括号把 6 括起来就不会报错
{}.toString() 转换报错,{}计算机不晓得是代码块还是一个对象, 括号括起来输入 [object Object]
[].toString() 数组中每一个元素以字符串模式输入,这里输入空

[]==[] false, 比拟援用,援用值不一样
[]==![] true [] 地址不为空,![]为 false

1. 如果两个值类型雷同,则比拟他们的值或者援用地址
2. 如果两个值类型不同,他们可能相等。依据上面规定进行类型转换再比拟:

  • 1. 如果一个是 null、一个是 undefined,那么相等。
  • 2. 如果一个是字符串,一个是数值,把字符串转换成数值再进行比拟。
  • 3. 如果任一值是 true,把它转换成 1 再比拟;如果任一值是 false,把它转换成 0 再比拟。
  • 4. 如果一个是对象,另一个是数值或字符串,把对象转换成根底类型的值再比拟。对象转换成根底类型,利用它的 toString 或者 valueOf 办法。

问题 11 SVG Canvas

SVG

  • 不依赖分辨率(矢量图)
  • 每一个图形都是一个 DOM 元素
  • 反对事件处理器
  • 适宜大型渲染区域的应用程序(谷歌地图)
  • 能够通过脚本和 CSS 进行批改
  • 只能通过脚本批改对象数量较小 (<10k)、图面更大时性能更佳
  • 不适宜游戏利用

Canvas

  • 依赖分辨率(位图)
  • 单个 HTML 元素,相当于 <img>
  • 不反对事件处理器
  • 文本渲染能力差
  • 图面较小,对象数量较大(>10k)时性能最佳
  • 适宜图像密集型的游戏利用

问题 12 ‘1’.toString()为什么能够调用?

var s = new Object('1');
s.toString();
s = null;
  1. 创立 Object 类实例。因为 Symbol 和 BigInt 的呈现,对它们调用 new 都会报错,目前 ES6 标准也不倡议用 new 来创立根本类型的包装类。
  2. 调用实例办法。
  3. 执行完办法立刻销毁这个实例。

整个过程体现了根本包装类型的性质,而根本包装类型恰好属于根本数据类型,包含 Boolean, Number 和 String。

问题 13 Object.is

Object 在严格等于的根底上修复了一些非凡状况下的失误,具体来说就是 + 0 和 -0,NaN 和 NaN。


function is(x, y) {if (x === y) {
    // 运行到 1 /x === 1/ y 的时候 x 和 y 都为 0,然而 1 /+0 = +Infinity,1/-0 = -Infinity, 是不一样的
    return x !== 0 || y !== 0 || 1 / x === 1 / y;
  } else {
    //NaN===NaN 是 false, 这是不对的,咱们在这里做一个拦挡,x !== x,那么肯定是 NaN, y 同理
    // 两个都是 NaN 的时候返回 true
    return x !== x && y !== y;
  }
 

问题 14, 浏览器不反对Promise.allSettled

当浏览器不反对 Promise.allSettled,能够如此 polyfill

if (!Promise.allSettled) {const rejectHandler = reason => ({status: "rejected", reason})
  const resolveHandler = value => ({status: "fulfilled", value})
  Promise.allSettled = promises =>
    Promise.all(promises.map((promise) =>
        Promise.resolve(promise) 
          .then(resolveHandler, rejectHandler)
      )
      // 每个 promise 须要用 Promise.resolve 包裹下
      // 以防传递非 promise
    );
}

问题 15

如何让 (a == 1 && a == 2 && a == 3) 的值为 true?
部署[Symbol.toPrimitive] 接口

let a = {[Symbol.toPrimitive]: (function (hint) {
    let i = 1;
    return function () {return i++;};
  })(),};

或者数据劫持

let i =1
let a = new Proxy({},{
  i:1,
  get:function(){return ()=>this.i++
  }
})

正文完
 0