JavaScript 使用 Number 类型来表示数字(整数或浮点数),遵循 IEEE 754 标准,通过 64 位来表示一个数字(1 + 11 + 52)
最大安全数字:Number.MAX_SAFE_INTEGER = Math.pow(2, 53) - 1,转换成整数就是 16 位,所以 0.1 === 0.1,是因为通过 toPrecision(16) 去有效位之后,两者是相等的。
在两数相加时,会先转换成二进制,0.1 和 0.2 转换成二进制的时候尾数会发生无限循环,然后进行对阶运算,JS 引擎对二进制进行截断,所以造成精度丢失。
所以总结:精度丢失可能出现在进制转换和对阶运算中
----问题知识点分割线----
响应式页面中经常用到根据屏幕密度设置不同的图片。这时就用到了 img 标签的srcset属性。srcset属性用于设置不同屏幕密度下,img 会自动加载不同的图片。用法如下:
<img src="image-128.png" srcset="image-256.png 2x" />
使用上面的代码,就能实现在屏幕密度为1x的情况下加载image-128.png, 屏幕密度为2x时加载image-256.png。
按照上面的实现,不同的屏幕密度都要设置图片地址,目前的屏幕密度有1x,2x,3x,4x四种,如果每一个图片都设置4张图片,加载就会很慢。所以就有了新的srcset标准。代码如下:
<img src="image-128.png"
srcset="image-128.png 128w, image-256.png 256w, image-512.png 512w"
sizes="(max-width: 360px) 340px, 128px" />
其中srcset指定图片的地址和对应的图片质量。sizes用来设置图片的尺寸零界点。对于 srcset 中的 w 单位,可以理解成图片质量。如果可视区域小于这个质量的值,就可以使用。浏览器会自动选择一个最小的可用图片。
sizes语法如下:
sizes="[media query] [length], [media query] [length] ... "
sizes就是指默认显示128px, 如果视区宽度大于360px, 则显示340px。
----问题知识点分割线----
在JavaScript中是使用构造函数来新建一个对象的,每一个构造函数的内部都有一个 prototype 属性,它的属性值是一个对象,这个对象包含了可以由该构造函数的所有实例共享的属性和方法。当使用构造函数新建一个对象后,在这个对象的内部将包含一个指针,这个指针指向构造函数的 prototype 属性对应的值,在 ES5 中这个指针被称为对象的原型。一般来说不应该能够获取到这个值的,但是现在浏览器中都实现了 proto 属性来访问这个属性,但是最好不要使用这个属性,因为它不是规范中规定的。ES5 中新增了一个 Object.getPrototypeOf() 方法,可以通过这个方法来获取对象的原型。
当访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念。原型链的尽头一般来说都是 Object.prototype 所以这就是新建的对象为什么能够使用 toString() 等方法的原因。
特点: JavaScript 对象是通过引用来传递的,创建的每个新对象实体中并没有一份属于自己的原型副本。当修改原型时,与之相关的对象也会继承这一改变。
----问题知识点分割线----
一个完整的URL包括以下几部分:
----问题知识点分割线----
这两个属性都是让元素隐藏,不可见。两者区别如下:
(1)在渲染树中
display:none
会让元素完全从渲染树中消失,渲染时不会占据任何空间;visibility:hidden
不会让元素从渲染树中消失,渲染的元素还会占据相应的空间,只是内容不可见。(2)是否是继承属性
display:none
是非继承属性,子孙节点会随着父节点从渲染树消失,通过修改子孙节点的属性也无法显示;visibility:hidden
是继承属性,子孙节点消失是由于继承了hidden
,通过设置visibility:visible
可以让子孙节点显示;
(3)修改常规文档流中元素的 display
通常会造成文档的重排,但是修改visibility
属性只会造成本元素的重绘;(4)如果使用读屏器,设置为display:none
的内容不会被读取,设置为visibility:hidden
的内容会被读取。
----问题知识点分割线----
.parent { position: relative;} .child { position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);}
.parent {
position: relative;
}
.child {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px; /* 自身 height 的一半 */
margin-left: -50px; /* 自身 width 的一半 */
}
.parent {
display: flex;
justify-content:center;
align-items:center;
}
----问题知识点分割线----
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
}
async function async2() {
console.log("async2");
}
async1();
console.log('start')
输出结果如下:
async1 start
async2
start
async1 end
代码的执行过程如下:
async1 start
,之后遇到了await
,它会阻塞async1
后面代码的执行,因此会先去执行async2
中的同步代码async2
,然后跳出async1
;async1
函数后,执行同步代码start
;await
后面的内容async1 end
。这里可以理解为await后面的语句相当于放到了new Promise中,下一行及之后的语句相当于放在Promise.then中。
----问题知识点分割线----
let arr = [1,1,"1","1",true,true,"true",{},{},"{}",null,null,undefined,undefined]
// 方法1
let uniqueOne = Array.from(new Set(arr)) console.log(uniqueOne)
// 方法2
let uniqueTwo = arr => {
let map = new Map(); //或者用空对象 let obj = {} 利用对象属性不能重复得特性
let brr = []
arr.forEach( item => {
if(!map.has(item)) { //如果是对象得话就判断 !obj[item]
map.set(item,true) //如果是对象得话就obj[item] =true 其他一样
brr.push(item)
}
})
return brr
}
console.log(uniqueTwo(arr))
//方法3
let uniqueThree = arr => {
let brr = []
arr.forEach(item => {
// 使用indexOf 返回数组是否包含某个值 没有就返回-1 有就返回下标
if(brr.indexOf(item) === -1) brr.push(item)
// 或者使用includes 返回数组是否包含某个值 没有就返回false 有就返回true
if(!brr.includes(item)) brr.push(item)
})
return brr
}
console.log(uniqueThree(arr))
//方法4
let uniqueFour = arr => {
// 使用 filter 返回符合条件的集合
let brr = arr.filter((item,index) => {
return arr.indexOf(item) === index
})
return brr
}
console.log(uniqueFour(arr))
----问题知识点分割线----
浅克隆:
function shallowClone(obj) {
let cloneObj = {};
for (let i in obj) {
cloneObj[i] = obj[i];
}
return cloneObj;
}
深克隆:
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;
}
----问题知识点分割线----
描述:使用setTimeout
模拟实现setInterval
的功能。
实现:
const mySetInterval(fn, time) {
let timer = null;
const interval = () => {
timer = setTimeout(() => {
fn(); // time 时间之后会执行真正的函数fn
interval(); // 同时再次调用interval本身
}, time)
}
interval(); // 开始执行
// 返回用于关闭定时器的函数
return () => clearTimeout(timer);
}
// 测试
const cancel = mySetInterval(() => console.log(1), 400);
setTimeout(() => {
cancel();
}, 1000);
// 打印两次1
----问题知识点分割线----
基本概念:
HTTP,全称为 HyperText Transfer Protocol,即为超文本传输协议。是互联网应用最为广泛的一种网络协议
所有的 www 文件都必须遵守这个标准。
http特性:
HTTP 是无连接无状态的
HTTP 一般构建于 TCP/IP 协议之上,默认端口号是 80
HTTP 可以分为两个部分,即请求和响应。
http请求:
HTTP 定义了在与服务器交互的不同方式,最常用的方法有 4 种
分别是 GET,POST,PUT, DELETE。URL 全称为资源描述符,可以这么认为:一个 URL 地址
对应着一个网络上的资源,而 HTTP 中的 GET,POST,PUT,DELETE
就对应着对这个资源的查询,修改,增添,删除4个操作。
HTTP 请求由 3 个部分构成,分别是:状态行,请求头(Request Header),请求正文。
HTTP 响应由 3 个部分构成,分别是:状态行,响应头(Response Header),响应正文。
HTTP 响应中包含一个状态码,用来表示服务器对客户端响应的结果。
状态码一般由3位构成:
1xx : 表示请求已经接受了,继续处理。
2xx : 表示请求已经处理掉了。
3xx : 重定向。
4xx : 一般表示客户端有错误,请求无法实现。
5xx : 一般为服务器端的错误。
比如常见的状态码:
200 OK 客户端请求成功。
301 Moved Permanently 请求永久重定向。
302 Moved Temporarily 请求临时重定向。
304 Not Modified 文件未修改,可以直接使用缓存的文件。
400 Bad Request 由于客户端请求有语法错误,不能被服务器所理解。
401 Unauthorized 请求未经授权,无法访问。
403 Forbidden 服务器收到请求,但是拒绝提供服务。服务器通常会在响应正文中给出不提供服务的原因。
404 Not Found 请求的资源不存在,比如输入了错误的URL。
500 Internal Server Error 服务器发生不可预期的错误,导致无法完成客户端的请求。
503 Service Unavailable 服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常。
大概还有一些关于http请求和响应头信息的介绍。
----问题知识点分割线----
class EventListener {
listeners = {};
on(name, fn) {
(this.listeners[name] || (this.listeners[name] = [])).push(fn)
}
once(name, fn) {
let tem = (...args) => {
this.removeListener(name, fn)
fn(...args)
}
fn.fn = tem
this.on(name, tem)
}
removeListener(name, fn) {
if (this.listeners[name]) {
this.listeners[name] = this.listeners[name].filter(listener => (listener != fn && listener != fn.fn))
}
}
removeAllListeners(name) {
if (name && this.listeners[name]) delete this.listeners[name]
this.listeners = {}
}
emit(name, ...args) {
if (this.listeners[name]) {
this.listeners[name].forEach(fn => fn.call(this, ...args))
}
}
}
----问题知识点分割线----
----问题知识点分割线----
问题描述: 两个块级元素的上外边距和下外边距可能会合并(折叠)为一个外边距,其大小会取其中外边距值大的那个,这种行为就是外边距折叠。需要注意的是,浮动的元素和绝对定位这种脱离文档流的元素的外边距不会折叠。重叠只会出现在垂直方向。
计算原则: 折叠合并后外边距的计算原则如下:
解决办法: 对于折叠的情况,主要有两种:兄弟之间重叠和父子之间重叠 (1)兄弟之间重叠
display: inline-block
float
absolute/fixed
(2)父子之间重叠
overflow: hidden
border:1px solid transparent
display: inline-block
----问题知识点分割线----
三栏布局一般指的是页面中一共有三栏,左右两栏宽度固定,中间自适应的布局,三栏布局的具体实现:
.outer {
position: relative;
height: 100px;
}
.left {
position: absolute;
width: 100px;
height: 100px;
background: tomato;
}
.right {
position: absolute;
top: 0;
right: 0;
width: 200px;
height: 100px;
background: gold;
}
.center {
margin-left: 100px;
margin-right: 200px;
height: 100px;
background: lightgreen;
}
.outer {
display: flex;
height: 100px;
}
.left {
width: 100px;
background: tomato;
}
.right {
width: 100px;
background: gold;
}
.center {
flex: 1;
background: lightgreen;
}
.outer {
height: 100px;
}
.left {
float: left;
width: 100px;
height: 100px;
background: tomato;
}
.right {
float: right;
width: 200px;
height: 100px;
background: gold;
}
.center {
height: 100px;
margin-left: 100px;
margin-right: 200px;
background: lightgreen;
}
.outer {
height: 100px;
padding-left: 100px;
padding-right: 200px;
}
.left {
position: relative;
left: -100px;
float: left;
margin-left: -100%;
width: 100px;
height: 100px;
background: tomato;
}
.right {
position: relative;
left: 200px;
float: right;
margin-left: -200px;
width: 200px;
height: 100px;
background: gold;
}
.center {
float: left;
width: 100%;
height: 100px;
background: lightgreen;
}
.outer {
height: 100px;
}
.left {
float: left;
margin-left: -100%;
width: 100px;
height: 100px;
background: tomato;
}
.right {
float: left;
margin-left: -200px;
width: 200px;
height: 100px;
background: gold;
}
.wrapper {
float: left;
width: 100%;
height: 100px;
background: lightgreen;
}
.center {
margin-left: 100px;
margin-right: 200px;
height: 100px;
}
----问题知识点分割线----
Promise.resolve().then(() => {
console.log('promise1');
const timer2 = setTimeout(() => {
console.log('timer2')
}, 0)
});
const timer1 = setTimeout(() => {
console.log('timer1')
Promise.resolve().then(() => {
console.log('promise2')
})
}, 0)
console.log('start');
输出结果如下:
start
promise1
timer1
promise2
timer2
代码执行过程如下:
Promise.resolve().then
是一个微任务,加入微任务队列start
Promise.resolve().then
,打印出promise1
timer2
,它是一个宏任务,将其加入宏任务队列,此时宏任务队列有两个任务,分别是timer1
、timer2
;timer1
,打印timer1
;Promise.resolve().then
,它是一个微任务,加入微任务队列promise2
;timer2
定时器,打印出timer2
;----问题知识点分割线----
----问题知识点分割线----
因为浏览器出于安全考虑,有同源策略。也就是说,如果协议、域名或者端口有一个不同就是跨域,Ajax 请求会失败。
为来防止CSRF攻击
1.JSONP
JSONP 的原理很简单,就是利用 <script> 标签没有跨域限制的漏洞。 通过 <script> 标签指向一个需要访问的地址并提供一个回调函数来接收数据当需要通讯时。 <script src="http://domain/api?param1=a¶m2=b&callback=jsonp"></script>
<script>
function jsonp(data) { console.log(data) } </script>
JSONP 使用简单且兼容性不错,但是只限于 get 请求。
2.CORS
CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。
3.document.domain
该方式只能用于二级域名相同的情况下,比如 a.test.com 和 b.test.com 适用于该方式。
只需要给页面添加 document.domain = 'test.com' 表示二级域名都相同就可以实现跨域
4.webpack配置proxyTable设置开发环境跨域
5.nginx代理跨域
6.iframe跨域
7.postMessage
这种方式通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息
----问题知识点分割线----
如果是 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 请求数也是可以没有上限地持续发送
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有