网站建设空间主机的选择网站备案 空间备案 域名备案
- 作者: 五速梦信息网
- 时间: 2026年03月21日 07:45
当前位置: 首页 > news >正文
网站建设空间主机的选择,网站备案 空间备案 域名备案,人工智能网页设计素材,网站服务搭建有哪些可能引起前端安全的问题?
跨站脚本 (Cross-Site Scripting, XSS): ⼀种代码注⼊⽅式, 为了与 CSS 区分所以被称作 XSS。早期常⻅于⽹络论坛, 起因是⽹站没有对⽤户的输⼊进⾏严格的限制, 使得攻击者可以将脚本上传到帖⼦让其他⼈浏览到有恶意脚本的⻚⾯, 其注⼊⽅式很简…有哪些可能引起前端安全的问题?
跨站脚本 (Cross-Site Scripting, XSS): ⼀种代码注⼊⽅式, 为了与 CSS 区分所以被称作 XSS。早期常⻅于⽹络论坛, 起因是⽹站没有对⽤户的输⼊进⾏严格的限制, 使得攻击者可以将脚本上传到帖⼦让其他⼈浏览到有恶意脚本的⻚⾯, 其注⼊⽅式很简单包括但不限于 JavaScript / CSS / Flash 等iframe的滥⽤: iframe中的内容是由第三⽅来提供的默认情况下他们不受控制他们可以在iframe中运⾏JavaScirpt脚本、Flash插件、弹出对话框等等这可能会破坏前端⽤户体验跨站点请求伪造Cross-Site Request ForgeriesCSRF: 指攻击者通过设置好的陷阱强制对已完成认证的⽤户进⾏⾮预期的个⼈信息或设定信息等某些状态更新属于被动攻击恶意第三⽅库: ⽆论是后端服务器应⽤还是前端应⽤开发绝⼤多数时候都是在借助开发框架和各种类库进⾏快速开发⼀旦第三⽅库被植⼊恶意代码很容易引起安全问题。
写代码实现函数能够深度克隆基本类型
浅克隆
function shallowClone(obj) {let cloneObj {};for (let i in obj) {cloneObj[i] obj[i];}return cloneObj;
}
深克隆
考虑基础类型引用类型 RegExp、Date、函数 不是 JSON 安全的会丢失 constructor所有的构造函数都指向 Object破解循环引用
function deepCopy(obj) {if (typeof obj object) {var result obj.constructor Array ? [] : {};for (var i in obj) {result[i] typeof obj[i] object ? deepCopy(obj[i]) : obj[i];}} else {var result obj;}return result;
}
script src’xxx’ ’xxx’/外部js文件先加载还是onload先执行为什么
onload 是所以加载完成之后执行的
了解 this 嘛bindcallapply 具体指什么
它们都是函数的方法
call: Array.prototype.call(this, args1, args2]) apply: Array.prototype.apply(this, [args1, args2]) ES6 之前用来展开数组调用, foo.appy(null, [])ES6 之后使用 … 操作符
New 绑定 显示绑定 隐式绑定 默认绑定如果需要使用 bind 的柯里化和 apply 的数组解构绑定到 null尽可能使用 Object.create(null) 创建一个 DMZ 对象
四条规则
默认绑定没有其他修饰bind、apply、call)在非严格模式下定义指向全局对象在严格模式下定义指向 undefined
function foo() {console.log(this.a);
}var a 2;
foo();
隐式绑定调用位置是否有上下文对象或者是否被某个对象拥有或者包含那么隐式绑定规则会把函数调用中的 this 绑定到这个上下文对象。而且对象属性链只有上一层或者说最后一层在调用位置中起作用
function foo() {console.log(this.a);
}var obj {a: 2,foo: foo,
}obj.foo(); // 2
显示绑定通过在函数上运行 call 和 apply 来显示的绑定 this
function foo() {console.log(this.a);
}var obj {a: 2
};foo.call(obj);
显示绑定之硬绑定
function foo(something) {console.log(this.a, something);return this.a something;
}function bind(fn, obj) {return function() {return fn.apply(obj, arguments);};
}var obj {a: 2
}var bar bind(foo, obj);
New 绑定new 调用函数会创建一个全新的对象并将这个对象绑定到函数调用的 this。
New 绑定时如果是 new 一个硬绑定函数那么会用 new 新建的对象替换这个硬绑定 this
function foo(a) {this.a a;
}var bar new foo(2);
console.log(bar.a)
代码输出结果
// a
function Foo () {getName function () {console.log(1);}return this;
}
// b
Foo.getName function () {console.log(2);
}
// c
Foo.prototype.getName function () {console.log(3);
}
// d
var getName function () {console.log(4);
}
// e
function getName () {console.log(5);
}Foo.getName(); // 2
getName(); // 4
Foo().getName(); // 1
getName(); // 1
new Foo.getName(); // 2
new Foo().getName(); // 3
new new Foo().getName(); // 3
输出结果2 4 1 1 2 3 3
解析
Foo.getName() Foo为一个函数对象对象都可以有属性b 处定义Foo的getName属性为函数输出2getName() 这里看d、e处d为函数表达式e为函数声明两者区别在于变量提升函数声明的 5 会被后边函数表达式的 4 覆盖 Foo().getName() 这里要看a处在Foo内部将全局的getName重新赋值为 console.log(1) 的函数执行Foo()返回 this这个this指向windowFoo().getName() 即为window.getName()输出 1getName() 上面3中全局的getName已经被重新赋值所以这里依然输出 1new Foo.getName() 这里等价于 new (Foo.getName())先执行 Foo.getName()输出 2然后new一个实例new Foo().getName() 这 里等价于 (new Foo()).getName(), 先new一个Foo的实例再执行这个实例的getName方法但是这个实例本身没有这个方法所以去原型链protot上边找实例.protot Foo.prototype所以输出 3new new Foo().getName() 这里等价于new (new Foo().getName())如上述6先输出 3然后new 一个 new Foo().getName() 的实例。
一个 tcp 连接能发几个 http 请求
如果是 HTTP 1.0 版本协议一般情况下不支持长连接因此在每次请求发送完毕之后TCP 连接即会断开因此一个 TCP 发送一个 HTTP 请求但是有一种情况可以将一条 TCP 连接保持在活跃状态那就是通过 Connection 和 Keep-Alive 首部在请求头带上 Connection: Keep-Alive并且可以通过 Keep-Alive 通用首部中指定的用逗号分隔的选项调节 keep-alive 的行为如果客户端和服务端都支持那么其实也可以发送多条不过此方式也有限制可以关注《HTTP 权威指南》4.5.5 节对于 Keep-Alive 连接的限制和规则。
而如果是 HTTP 1.1 版本协议支持了长连接因此只要 TCP 连接不断开便可以一直发送 HTTP 请求持续不断没有上限 同样如果是 HTTP 2.0 版本协议支持多用复用一个 TCP 连接是可以并发多个 HTTP 请求的同样也是支持长连接因此只要不断开 TCP 的连接HTTP 请求数也是可以没有上限地持续发送
参考 前端进阶面试题详细解答
什么是同源策略
跨域问题其实就是浏览器的同源策略造成的。 同源策略限制了从同一个源加载的文档或脚本如何与另一个源的资源进行交互。这是浏览器的一个用于隔离潜在恶意文件的重要的安全机制。同源指的是协议、端口号、域名必须一致。 同源策略protocol协议、domain域名、port端口三者必须一致。
同源政策主要限制了三个方面
当前域下的 js 脚本不能够访问其他域下的 cookie、localStorage 和 indexDB。当前域下的 js 脚本不能够操作访问操作其他域下的 DOM。当前域下 ajax 无法发送跨域请求。
同源政策的目的主要是为了保证用户的信息安全它只是对 js 脚本的一种限制并不是对浏览器的限制对于一般的 img、或者script 脚本请求都不会有跨域的限制这是因为这些操作都不会通过响应结果来进行可能出现安全问题的操作。
说下对 JS 的了解吧
是基于原型的动态语言主要独特特性有 this、原型和原型链。
JS 严格意义上来说分为语言标准部分ECMAScript 宿主环境部分
语言标准部分
2015 年发布 ES6引入诸多新特性使得能够编写大型项目变成可能标准自 2015 之后以年号代号每年一更
宿主环境部分
在浏览器宿主环境包括 DOM BOM 等在 Node宿主环境包括一些文件、数据库、网络、与操作系统的交互等
React 17 带来了哪些改变 最重要的是以下三点 新的 JSX 转换逻辑事件系统重构Lane 模型的引入
- 重构 JSX 转换逻辑 在过去如果我们在 React 项目中写入下面这样的代码 function MyComponent() {return p这是我的组件/p }React 是会报错的原因是 React 中对 JSX 代码的转换依赖的是 React.createElement 这个函数。因此但凡我们在代码中包含了 JSX那么就必须在文件中引入 React像下面这样 import React from react; function MyComponent() {return p这是我的组件/p }而 React 17 则允许我们在不引入 React 的情况下直接使用 JSX。这是因为在 React 17 中编译器会自动帮我们引入 JSX 的解析器也就是说像下面这样一段逻辑 function MyComponent() {return p这是我的组件/p }会被编译器转换成这个样子 import {jsx as _jsx} from react/jsx-runtime; function MyComponent() {return _jsx(p, { children: 这是我的组件 }); }react/jsx-runtime 中的 JSX 解析器将取代 React.createElement 完成 JSX 的编译工作这个过程对开发者而言是自动化、无感知的。因此新的 JSX 转换逻辑带来的最显著的改变就是降低了开发者的学习成本。 react/jsx-runtime 中的 JSX 解析器看上去似乎在调用姿势上和 React.createElement 区别不大那么它是否只是 React.createElement 换了个马甲呢当然不是它在内部实现了 React.createElement 无法做到的性能优化和简化。在一定情况下它可能会略微改善编译输出内容的大小
- 事件系统重构 事件系统在 React 17 中的重构要从以下两个方面来看 卸掉历史包袱拥抱新的潮流 2.1 卸掉历史包袱放弃利用 document 来做事件的中心化管控 React 16.13.x 版本中的事件系统会通过将所有事件冒泡到 document 来实现对事件的中心化管控 这样的做法虽然看上去已经足够巧妙但仍然有它不聪明的地方——document 是整个文档树的根节点操作 document 带来的影响范围实在是太大了这将会使事情变得更加不可控 在 React 17 中React 团队终于正面解决了这个问题事件的中心化管控不会再全部依赖 document管控相关的逻辑被转移到了每个 React 组件自己的容器 DOM 节点中。比如说我们在 ID 为 root 的 DOM 节点下挂载了一个 React 组件像下面代码这样 const rootElement document.getElementById(root); ReactDOM.render(App /, rootElement);那么事件管控相关的逻辑就会被安装到 root 节点上去。这样一来 React 组件就能够自己玩自己的再也无法对全局的事件流构成威胁了 2.2 拥抱新的潮流放弃事件池 在 React 17 之前合成事件对象会被放进一个叫作“事件池”的地方统一管理。这样做的目的是能够实现事件对象的复用进而提高性能每当事件处理函数执行完毕后其对应的合成事件对象内部的所有属性都会被置空意在为下一次被复用做准备。这也就意味着事件逻辑一旦执行完毕我们就拿不到事件对象了React 官方给出的这个例子就很能说明问题请看下面这个代码 function handleChange(e) {// This wont work because the event object gets reused.setTimeout(() {console.log(e.target.value); // Too late!}, 100); }异步执行的 setTimeout 回调会在 handleChange 这个事件处理函数执行完毕后执行因此它拿不到想要的那个事件对象 e。 要想拿到目标事件对象必须显式地告诉 React——我永远需要它也就是调用 e.persist() 函数像下面这样 function handleChange(e) {// Prevents React from resetting its properties:e.persist();setTimeout(() {console.log(e.target.value); // Works}, 100); }在 React 17 中我们不需要 e.persist()也可以随时随地访问我们想要的事件对象。
- Lane 模型的引入 初学 React 源码的同学由此可能会很自然地认为优先级就应该是用 Lane 来处理的。但事实上React 16 中处理优先级采用的是 expirationTime 模型。 expirationTime 模型使用 expirationTime一个时间长度 来描述任务的优先级而 Lane 模型则使用二进制数来表示任务的优先级 lane 模型通过将不同优先级赋值给一个位通过 31 位的位运算来操作优先级。 Lane 模型提供了一个新的优先级排序的思路相对于 expirationTime 来说它对优先级的处理会更细腻能够覆盖更多的边界条件。 浏览器的渲染过程 浏览器渲染主要有以下步骤 首先解析收到的文档根据文档定义构建一棵 DOM 树DOM 树是由 DOM 元素及属性节点组成的。然后对 CSS 进行解析生成 CSSOM 规则树。根据 DOM 树和 CSSOM 规则树构建渲染树。渲染树的节点被称为渲染对象渲染对象是一个包含有颜色和大小等属性的矩形渲染对象和 DOM 元素相对应但这种对应关系不是一对一的不可见的 DOM 元素不会被插入渲染树。还有一些 DOM元素对应几个可见对象它们一般是一些具有复杂结构的元素无法用一个矩形来描述。当渲染对象被创建并添加到树中它们并没有位置和大小所以当浏览器生成渲染树以后就会根据渲染树来进行布局也可以叫做回流。这一阶段浏览器要做的事情是要弄清楚各个节点在页面中的确切位置和大小。通常这一行为也被称为“自动重排”。布局阶段结束后是绘制阶段遍历渲染树并调用渲染对象的 paint 方法将它们的内容显示在屏幕上绘制使用 UI 基础组件。 大致过程如图所示 注意 这个过程是逐步完成的为了更好的用户体验渲染引擎将会尽可能早的将内容呈现到屏幕上并不会等到所有的html 都解析完成之后再去构建和布局 render 树。它是解析完一部分内容就显示一部分内容同时可能还在通过网络下载其余内容。 进程与线程的概念 从本质上说进程和线程都是 CPU 工作时间片的一个描述 进程描述了 CPU 在运行指令及加载和保存上下文所需的时间放在应用上来说就代表了一个程序。线程是进程中的更小单位描述了执行一段指令所需的时间。 进程是资源分配的最小单位线程是CPU调度的最小单位。 一个进程就是一个程序的运行实例。详细解释就是启动一个程序的时候操作系统会为该程序创建一块内存用来存放代码、运行中的数据和一个执行任务的主线程我们把这样的一个运行环境叫进程。进程是运行在虚拟内存上的虚拟内存是用来解决用户对硬件资源的无限需求和有限的硬件资源之间的矛盾的。从操作系统角度来看虚拟内存即交换文件从处理器角度看虚拟内存即虚拟地址空间。 如果程序很多时内存可能会不够操作系统为每个进程提供一套独立的虚拟地址空间从而使得同一块物理内存在不同的进程中可以对应到不同或相同的虚拟地址变相的增加了程序可以使用的内存。 进程和线程之间的关系有以下四个特点 1进程中的任意一线程执行出错都会导致整个进程的崩溃。 2线程之间共享进程中的数据。 3当一个进程关闭之后操作系统会回收进程所占用的内存 当一个进程退出时操作系统会回收该进程所申请的所有资源即使其中任意线程因为操作不当导致内存泄漏当进程退出时这些内存也会被正确回收。 4进程之间的内容相互隔离。 进程隔离就是为了使操作系统中的进程互不干扰每一个进程只能访问自己占有的数据也就避免出现进程 A 写入数据到进程 B 的情况。正是因为进程之间的数据是严格隔离的所以一个进程如果崩溃了或者挂起了是不会影响到其他进程的。如果进程之间需要进行数据的通信这时候就需要使用用于进程间通信的机制了。 Chrome浏览器的架构图 从图中可以看出最新的 Chrome 浏览器包括 1 个浏览器主进程1 个 GPU 进程1 个网络进程多个渲染进程多个插件进程 这些进程的功能 浏览器进程主要负责界面显示、用户交互、子进程管理同时提供存储等功能。渲染进程核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中默认情况下Chrome 会为每个 Tab 标签创建一个渲染进程。出于安全考虑渲染进程都是运行在沙箱模式下。GPU 进程其实 GPU 的使用初衷是为了实现 3D CSS 的效果只是随后网页、Chrome 的 UI 界面都选择采用 GPU 来绘制这使得 GPU 成为浏览器普遍的需求。最后Chrome 在其多进程架构上也引入了 GPU 进程。网络进程主要负责页面的网络资源加载之前是作为一个模块运行在浏览器进程里面的直至最近才独立出来成为一个单独的进程。插件进程主要是负责插件的运行因插件易崩溃所以需要通过插件进程来隔离以保证插件进程崩溃不会对浏览器和页面造成影响。 所以打开一个网页最少需要四个进程1 个网络进程、1 个浏览器进程、1 个 GPU 进程以及 1 个渲染进程。如果打开的页面有运行插件的话还需要再加上 1 个插件进程。 虽然多进程模型提升了浏览器的稳定性、流畅性和安全性但同样不可避免地带来了一些问题 更高的资源占用因为每个进程都会包含公共基础结构的副本如 JavaScript 运行环境这就意味着浏览器会消耗更多的内存资源。更复杂的体系架构浏览器各模块之间耦合性高、扩展性差等问题会导致现在的架构已经很难适应新的需求了。 对对象与数组的解构的理解 解构是 ES6 提供的一种新的提取数据的模式这种模式能够从对象或数组里有针对性地拿到想要的数值。 1数组的解构 在解构数组时以元素的位置为匹配条件来提取想要的数据的 const [a, b, c] [1, 2, 3] 最终a、b、c分别被赋予了数组第0、1、2个索引位的值 数组里的0、1、2索引位的元素值精准地被映射到了左侧的第0、1、2个变量里去这就是数组解构的工作模式。还可以通过给左侧变量数组设置空占位的方式实现对数组中某几个元素的精准提取 const [a,,c] [1,2,3] 通过把中间位留空可以顺利地把数组第一位和最后一位的值赋给 a、c 两个变量 2对象的解构 对象解构比数组结构稍微复杂一些也更显强大。在解构对象时是以属性的名称为匹配条件来提取想要的数据的。现在定义一个对象 const stu {name: Bob,age: 24 } 假如想要解构它的两个自有属性可以这样 const { name, age } stu 这样就得到了 name 和 age 两个和 stu 平级的变量 注意对象解构严格以属性名作为定位依据所以就算调换了 name 和 age 的位置结果也是一样的 const { age, name } stu 什么是 XSS 攻击 1概念 XSS 攻击指的是跨站脚本攻击是一种代码注入攻击。攻击者通过在网站注入恶意脚本使之在用户的浏览器上运行从而盗取用户的信息如 cookie 等。 XSS 的本质是因为网站没有对恶意代码进行过滤与正常的代码混合在一起了浏览器没有办法分辨哪些脚本是可信的从而导致了恶意代码的执行。 攻击者可以通过这种攻击方式可以进行以下操作 获取页面的数据如DOM、cookie、localStorageDOS攻击发送合理请求占用服务器资源从而使用户无法访问服务器破坏页面结构流量劫持将链接指向某网站 2攻击类型 XSS 可以分为存储型、反射型和 DOM 型 存储型指的是恶意脚本会存储在目标服务器上当浏览器请求数据时脚本从服务器传回并执行。反射型指的是攻击者诱导用户访问一个带有恶意代码的 URL 后服务器端接收数据后处理然后把带有恶意代码的数据发送到浏览器端浏览器端解析这段带有 XSS 代码的数据后当做脚本执行最终完成 XSS 攻击。DOM 型指的通过修改页面的 DOM 节点形成的 XSS。 1存储型 XSS 的攻击步骤 攻击者将恶意代码提交到⽬标⽹站的数据库中。⽤户打开⽬标⽹站时⽹站服务端将恶意代码从数据库取出拼接在 HTML 中返回给浏览器。⽤户浏览器接收到响应后解析执⾏混在其中的恶意代码也被执⾏。恶意代码窃取⽤户数据并发送到攻击者的⽹站或者冒充⽤户的⾏为调⽤⽬标⽹站接⼝执⾏攻击者指定的操作。 这种攻击常⻅于带有⽤户保存数据的⽹站功能如论坛发帖、商品评论、⽤户私信等。 2反射型 XSS 的攻击步骤 攻击者构造出特殊的 URL其中包含恶意代码。⽤户打开带有恶意代码的 URL 时⽹站服务端将恶意代码从 URL 中取出拼接在 HTML 中返回给浏览器。⽤户浏览器接收到响应后解析执⾏混在其中的恶意代码也被执⾏。恶意代码窃取⽤户数据并发送到攻击者的⽹站或者冒充⽤户的⾏为调⽤⽬标⽹站接⼝执⾏攻击者指定的操作。 反射型 XSS 跟存储型 XSS 的区别是存储型 XSS 的恶意代码存在数据库⾥反射型 XSS 的恶意代码存在 URL ⾥。 反射型 XSS 漏洞常⻅于通过 URL 传递参数的功能如⽹站搜索、跳转等。 由于需要⽤户主动打开恶意的 URL 才能⽣效攻击者往往会结合多种⼿段诱导⽤户点击。 3DOM 型 XSS 的攻击步骤 攻击者构造出特殊的 URL其中包含恶意代码。⽤户打开带有恶意代码的 URL。⽤户浏览器接收到响应后解析执⾏前端 JavaScript 取出 URL 中的恶意代码并执⾏。恶意代码窃取⽤户数据并发送到攻击者的⽹站或者冒充⽤户的⾏为调⽤⽬标⽹站接⼝执⾏攻击者指定的操作。 DOM 型 XSS 跟前两种 XSS 的区别DOM 型 XSS 攻击中取出和执⾏恶意代码由浏览器端完成属于前端JavaScript ⾃身的安全漏洞⽽其他两种 XSS 都属于服务端的安全漏洞。 对节流与防抖的理解 函数防抖是指在事件被触发 n 秒后再执行回调如果在这 n 秒内事件又被触发则重新计时。这可以使用在一些点击请求的事件上避免因为用户的多次点击向后端发送多次请求。函数节流是指规定一个单位时间在这个单位时间内只能有一次触发事件的回调函数执行如果在同一个单位时间内某事件被触发多次只有一次能生效。节流可以使用在 scroll 函数的事件监听上通过事件节流来降低事件调用的频率。 防抖函数的应用场景 按钮提交场景防⽌多次提交按钮只执⾏最后提交的⼀次服务端验证场景表单验证需要服务端配合只执⾏⼀段连续的输⼊事件的最后⼀次还有搜索联想词功能类似⽣存环境请⽤lodash.debounce 节流函数的适⽤场景 拖拽场景固定时间内只执⾏⼀次防⽌超⾼频次触发位置变动缩放场景监控浏览器resize动画场景避免短时间内多次触发动画引起性能问题 Number() 的存储空间是多大如果后台发送了一个超过最大自己的数字怎么办 Math.pow(2, 53) 53 为有效数字会发生截断等于 JS 能支持的最大数字。 死锁产生的原因 如果解决死锁的问题 所谓死锁是指多个进程在运行过程中因争夺资源而造成的一种僵局当进程处于这种僵持状态时若无外力作用它们都将无法再向前推进。 系统中的资源可以分为两类 可剥夺资源是指某进程在获得这类资源后该资源可以再被其他进程或系统剥夺CPU和主存均属于可剥夺性资源不可剥夺资源当系统把这类资源分配给某进程后再不能强行收回只能在进程用完后自行释放如磁带机、打印机等。 产生死锁的原因 1竞争资源 产生死锁中的竞争资源之一指的是竞争不可剥夺资源例如系统中只有一台打印机可供进程P1使用假定P1已占用了打印机若P2继续要求打印机打印将阻塞产生死锁中的竞争资源另外一种资源指的是竞争临时资源临时资源包括硬件中断、信号、消息、缓冲区内的消息等通常消息通信顺序进行不当则会产生死锁 2进程间推进顺序非法 若P1保持了资源R1P2保持了资源R2系统处于不安全状态因为这两个进程再向前推进便可能发生死锁。例如当P1运行到P1RequestR2时将因R2已被P2占用而阻塞当P2运行到P2RequestR1时也将因R1已被P1占用而阻塞于是发生进程死锁 产生死锁的必要条件 互斥条件进程要求对所分配的资源进行排它性控制即在一段时间内某资源仅为一进程所占用。请求和保持条件当进程因请求资源而阻塞时对已获得的资源保持不放。不剥夺条件进程已获得的资源在未使用完之前不能剥夺只能在使用完时由自己释放。环路等待条件在发生死锁时必然存在一个进程——资源的环形链。 预防死锁的方法 资源一次性分配一次性分配所有资源这样就不会再有请求了破坏请求条件只要有一个资源得不到分配也不给这个进程分配其他的资源破坏请保持条件可剥夺资源即当某进程获得了部分资源但得不到其它资源则释放已占有的资源破坏不可剥夺条件资源有序分配法系统给每类资源赋予一个编号每一个进程按编号递增的顺序请求资源释放则相反破坏环路等待条件 代码输出结果 const async1 async () {console.log(async1);setTimeout(() {console.log(timer1)}, 2000)await new Promise(resolve {console.log(promise1)})console.log(async1 end)return async1 success } console.log(script start); async1().then(res console.log(res)); console.log(script end); Promise.resolve(1).then(2).then(Promise.resolve(3)).catch(4).then(res console.log(res)) setTimeout(() {console.log(timer2) }, 1000) 输出结果如下 script start async1 promise1 script end 1 timer2 timer1 代码的执行过程如下 首先执行同步带吗打印出script start遇到定时器timer1将其加入宏任务队列之后是执行Promise打印出promise1由于Promise没有返回值所以后面的代码不会执行然后执行同步代码打印出script end继续执行下面的Promise.then和.catch期望参数是一个函数这里传入的是一个数字因此就会发生值渗透将resolve(1)的值传到最后一个then直接打印出1遇到第二个定时器将其加入到微任务队列执行微任务队列按顺序依次执行两个定时器但是由于定时器时间的原因会在两秒后先打印出timer2在四秒后打印出timer1。 判断数组的方式有哪些 通过Object.prototype.toString.call()做判断 Object.prototype.toString.call(obj).slice(8,-1) Array; 通过原型链做判断 obj.proto Array.prototype; 通过ES6的Array.isArray()做判断 Array.isArrray(obj); 通过instanceof做判断 obj instanceof Array 通过Array.prototype.isPrototypeOf Array.prototype.isPrototypeOf(obj) JS 隐式转换显示转换 一般非基础类型进行转换时会先调用 valueOf如果 valueOf 无法返回基本类型值就会调用 toString 字符串和数字 “” 操作符如果有一个为字符串那么都转化到字符串然后执行字符串拼接“-” 操作符转换为数字相减 (-a, a * 1 a/1) 都能进行隐式强制类型转换 [] {} 和 {} [] 布尔值到数字 1 true 21 false 1 转换为布尔值 for 中第二个whileif三元表达式|| 逻辑或 逻辑与左边的操作数 符号 不能被转换为数字能被转换为布尔值都是 true可以被转换成字符串 “Symbol(cool)” 宽松相等和严格相等 宽松相等允许进行强制类型转换而严格相等不允许 字符串与数字 转换为数字然后比较 其他类型与布尔类型 先把布尔类型转换为数字然后继续进行比较 对象与非对象 执行对象的 ToPrimitive(对象然后继续进行比较 假值列表 undefinednullfalse0, -0, NaN“” 什么是物理像素逻辑像素和像素密度为什么在移动端开发时需要用到3x, 2x这种图片 以 iPhone XS 为例当写 CSS 代码时针对于单位 px其宽度为 414px 896px也就是说当赋予一个 DIV元素宽度为 414px这个 DIV 就会填满手机的宽度 而如果有一把尺子来实际测量这部手机的物理像素实际为 1242*2688 物理像素经过计算可知1242/4143也就是说在单边上一个逻辑像素3个物理像素就说这个屏幕的像素密度为 3也就是常说的 3 倍屏。 对于图片来说为了保证其不失真1 个图片像素至少要对应一个物理像素假如原始图片是 500300 像素那么在 3 倍屏上就要放一个 1500900 像素的图片才能保证 1 个物理像素至少对应一个图片像素才能不失真。 当然也可以针对所有屏幕都只提供最高清图片。虽然低密度屏幕用不到那么多图片像素而且会因为下载多余的像素造成带宽浪费和下载延迟但从结果上说能保证图片在所有屏幕上都不会失真。 还可以使用 CSS 媒体查询来判断不同的像素密度从而选择不同的图片: my-image { background: (low.png); } media only screen and (min-device-pixel-ratio: 1.5) {#my-image { background: (high.png); } }
- 上一篇: 网站建设空间大小龙岗网站建设定制开发
- 下一篇: 网站建设來选宙斯站长网页推广怎么收取费用
相关文章
-
网站建设空间大小龙岗网站建设定制开发
网站建设空间大小龙岗网站建设定制开发
- 技术栈
- 2026年03月21日
-
网站建设课程设计内容在哪找做网站的
网站建设课程设计内容在哪找做网站的
- 技术栈
- 2026年03月21日
-
网站建设课程设计的引言工具网站有哪些
网站建设课程设计的引言工具网站有哪些
- 技术栈
- 2026年03月21日
-
网站建设來选宙斯站长网页推广怎么收取费用
网站建设來选宙斯站长网页推广怎么收取费用
- 技术栈
- 2026年03月21日
-
网站建设莱州哪家强?wordpress优秀的主题
网站建设莱州哪家强?wordpress优秀的主题
- 技术栈
- 2026年03月21日
-
网站建设栏目分析wordpress删除 自豪的
网站建设栏目分析wordpress删除 自豪的
- 技术栈
- 2026年03月21日
