HTML
在主框架下引入的iframe,检测这个iframe是否能打开,如果打不开则跳到404页面
我们知道 iframe 只有 onload 事件,没有 onerror 事件
非跨域
如果不跨域,那问题就很好解决了,有以下几种方案可以使用:
- 使用 ajax 发送一个 head 请求,看状态是否返回 200 (之所以发送 head 请求,是轻量级,响应速度快)。
- 检测 iframe 元素特征,在 iframe onload 触发后,检测 html 元素,例如有没有 title,内容是否为空等。
跨域
如果跨域的情况,要看你是否能控制跨域服务器。
兼容跨域/非跨域情况
- 使用定时器检测,如果onload触发时间晚于预设阈值,判定为无法加载。
- 使用link标签来测试url能否访问。
下面重点来讲下方案2。
link标签来测试url
我们为什么要使用link标签?
支持跨域的检测标签有如下几个:
- script
- img
- link
- video
- audio
支持 onload 和 onerror 的只有 script 、link、img
之所以不用 img、script的原因是:
- img会检测格式,如果不是图片类型,也会触发onerror。
- script可能会有安全问题(XSS等)。
能控制跨域服务器
可以使用 jsonp 或 CORS,允许客户端发送跨域 head 请求,来获取是否状态正常
如果不能跨域的情况,见下面的通用方案
<html>
<body>
<iframe id="iframe" onload="frameLoad()" width="100%" height="100%" src="https://baidu1.com">
</iframe>
<script>
function frameLoad() {
console.log('frame load')
}
function accessTest() {
var link = document.createElement('link')
link.rel = "stylesheet"
link.type = "text/css"
// 这里设置需要检测的url
link.href = "https://baidu1.com"
link.onload = function() {
console.log('accessTest success')
}
link.onerror = function() {
console.log('accessTest fail')
}
document.body.appendChild(link)
}
accessTest()
</script>
</body>
</html>
CSS
使用css如何拉伸字体
使用css3的front-stretch 但是很多游览器都不兼容
一般用display: inline-block;
+ transform: scale();
display: inline-block;
transform: scale(5,3);
-ms-transform: scale(5,3);
-webkit-transform: scale(5,3);
-moz-transform: scale(5,3);
-o-transform: scale(5,3);
JavaScript
ES6的Proxy是什么,有什么应用场景
proxy做数据劫持用的和Object.defineProperty类似但是它的功能更强大,可以直接监听对象而非属性,也可监听数组
Vue
你知道v-model的原理吗?说说看
本质上一个语法糖,就是靠:bind="value"与@change="value = $event.target.value"的结合。
<input type="text" :value="msg" @input="msg=$event.target.value">
{{msg}}
</input>
网络
讲一下 HTTP 与 HTTPS 的区别
http和https的主要区别是http是明文传输,http是传输的数据是加密过后的
http是80端口,https是443端口
http连接是无状态的,https是ssl+http构建的可加密传输,身份认证的网络协议,比http安全
https的缺点:
- HTTPS协议握手阶段比较费时,会使页面的加载时间延长近50%,增加10%到20%的耗电;
- HTTPS连接缓存不如HTTP高效,会增加数据开销和功耗,甚至已有的安全措施也会因此而受到影响;
- SSL证书需要钱,功能越强大的证书费用越高,个人网站、小网站没有必要一般不会用。
- SSL证书通常需要绑定IP,不能在同一IP上绑定多个域名,IPv4资源不可能支撑这个消耗。
- HTTPS协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用。最关键的,SSL证书的信用链体系并不安全,特别是在某些国家可以控制CA根证书的情况下,中间人攻击一样可行。
客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤,
-
客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。
-
Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
-
客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
-
客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
-
Web服务器利用自己的私钥解密出会话密钥。
-
Web服务器利用会话密钥加密与客户端之间的通信。
NodeJS
如何使用nodejs对base64进行编解码?
基础补充
介绍:
先说buffer类
Buffer
类是一个全局变量,用于直接处理二进制数据。 它可以使用多种方式构建。
如:
const buf1 = Buffer.from('this is cxy');
console.log(buf1) // <Buffer 74 68 69 73 20 69 73 20 63 78 79> 二进制显示的
console.log(buf1.toString()) // this is cxy
方法:
Buffer.alloc(size[, fill[, encoding]])
它的参数是:
size
新Buffer
的期望长度。fill
用于预填充新Buffer
的值。默认值:0
。encoding
如果fill
是一个字符串,则这是它的字符编码。默认值:'utf8'
。
分配一个大小为 size
字节的新 Buffer
。 如果 fill
为 undefined
,则用零填充 Buffer
。
const buf = Buffer.alloc(5);
console.log(buf);
// 打印: <Buffer 00 00 00 00 00>
const buf = Buffer.alloc(5, 'a');
console.log(buf);
// 打印: <Buffer 61 61 61 61 61>
const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64');
console.log(buf);
// 打印: <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
注意:调用 Buffer.alloc()
可能比替代的 Buffer.allocUnsafe()
慢得多,但能确保新创建的 Buffer
实例的内容永远不会包含来自先前分配的敏感数据,包括可能尚未分配给 Buffer
的数据。
Buffer.allocUnsafe(size)
它的参数是:
以这种方式创建的 Buffer
实例的底层内存是未初始化的。 新创建的 Buffer
的内容是未知的,可能包含敏感数据。 使用 Buffer.alloc()
可以创建以零初始化的 Buffer
实例。
const buf = Buffer.allocUnsafe(10);
console.log(buf);
// 打印(内容可能有所不同): <Buffer a0 8b 28 3f 01 00 00 00 50 32>
buf.fill(0);
console.log(buf);
// 打印: <Buffer 00 00 00 00 00 00 00 00 00 00>
注意:
Buffer
模块会预分配一个内部的大小为Buffer.poolSize
的Buffer
实例,作为快速分配的内存池,用于使用Buffer.allocUnsafe()
创建新的Buffer
实例、或Buffer.from(array)
、或Buffer.concat()
、或弃用的new Buffer(size)
构造器但仅当size
小于或等于Buffer.poolSize >> 1
(Buffer.poolSize
除以二再向下取整)。对这个预分配的内部内存池的使用是调用
Buffer.alloc(size, fill)
和Buffer.allocUnsafe(size).fill(fill)
两者之间的关键区别。 具体来说,Buffer.alloc(size, fill)
永远不会使用内部的Buffer
池,而Buffer.allocUnsafe(size).fill(fill)
在size
小于或等于Buffer.poolSize
的一半时将会使用内部的Buffer
池。 该差异虽然很微妙,但当应用程序需要Buffer.allocUnsafe()
提供的额外性能时,则非常重要。
Buffer.from(array)
已弃用:原api是 new Buffer(XXX)
参数:
array
使用 0
– 255
范围内的字节数组 array
来分配一个新的 Buffer
。 超出该范围的数组条目会被截断以适合它。
// 创建一个包含字符串 'buffer' 的 UTF-8 字节的新 Buffer。
const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);
Buffer.from(arrayBuffer[, byteOffset[, length]])
arrayBuffer
一个ArrayBuffer
或SharedArrayBuffer
,例如TypedArray
的.buffer
属性。byteOffset
开始拷贝的索引。默认值:0
。length
拷贝的字节数。默认值:arrayBuffer.byteLength - byteOffset
。
创建 ArrayBuffer
的视图,但不会拷贝底层内存。 例如,当传入 TypedArray
的 .buffer
属性的引用时,新建的 Buffer
会与 TypedArray
共享同一内存。
const arr = new Uint16Array(2);
arr[0] = 5000;
arr[1] = 4000;
// 与 `arr` 共享内存。
const buf = Buffer.from(arr.buffer);
console.log(buf);
// 打印: <Buffer 88 13 a0 0f>
// 改变原先的 Uint16Array 也会改变 Buffer。
arr[1] = 6000;
console.log(buf);
// 打印: <Buffer 88 13 70 17>
可选的 byteOffset
和 length
参数指定 arrayBuffer
中与 Buffer
共享的内存范围。
const ab = new ArrayBuffer(10);
const buf = Buffer.from(ab, 0, 2);
console.log(buf.length);
// 打印: 2
Buffer.from(string)
string
要编码的字符串。encoding
的字符编码。默认值:'utf8'
。
创建一个包含 string
的新 Buffer
。 encoding
参数指定用于将 string
转换为字节的字符编码。
const buf1 = Buffer.from('this is a tést');
const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); // hex是16进制
console.log(buf1.toString());
// 打印: this is a tést
console.log(buf2.toString());
// 打印: this is a tést
console.log(buf1.toString('latin1'));
// 打印: this is a tést
Buffer.from(buffer)
buffer
要拷贝数据的Buffer
或Uint8Array
。
拷贝 buffer
的数据到新建的 Buffer
实例。
const buf1 = Buffer.from('buffer');
const buf2 = Buffer.from(buf1);
buf1[0] = 0x61;
console.log(buf1.toString());
// 打印: auffer
console.log(buf2.toString());
// 打印: buffer
Buffer.from(object[, offsetOrEncoding[, length]])
object
支持Symbol.toPrimitive
或valueOf()
的对象。offsetOrEncoding
字节偏移量或字符编码。length
长度。
对于 valueOf()
返回值不严格等于 object
的对象,返回 Buffer.from(object.valueOf(), offsetOrEncoding, length)
。
const buf = Buffer.from(new String('this is a test'));
// 打印: <Buffer 74 68 69 73 20 69 73 20 61 20 74 65 73 74>
对于支持 Symbol.toPrimitive
的对象,会返回 Buffer.from(object[Symbol.toPrimitive]('string'), offsetOrEncoding)
。
class Foo {
[Symbol.toPrimitive]() {
return 'this is a test';
}
}
const buf = Buffer.from(new Foo(), 'utf8');
// 打印: <Buffer 74 68 69 73 20 69 73 20 61 20 74 65 73 74>
如果 object
没有提及的方法、或适用于 Buffer.from()
变量的其他类型,则抛出 TypeError
。
buf.toString([encoding[, start[, end]]])
encoding
使用的字符编码。默认值:'utf8'
。start
开始解码的字节偏移量。默认值:0
。end
结束解码的字节偏移量(不包含)。默认值:buf.length
。- 返回: String
根据 encoding
指定的字符编码将 buf
解码成字符串。 传入 start
和 end
可以只解码 buf
的子集。
如果 encoding
为 'utf8'
,并且输入中的字节序列不是有效的 UTF-8,则每个无效的字节都会由替换字符 U+FFFD
替换。
字符串的最大长度(以 UTF-16 为单位)可查看 buffer.constants.MAX_STRING_LENGTH
。
const buf1 = Buffer.allocUnsafe(26);
for (let i = 0; i < 26; i++) {
// 97 是 'a' 的十进制 ASCII 值。
buf1[i] = i + 97;
}
console.log(buf1.toString('utf8'));
// 打印: abcdefghijklmnopqrstuvwxyz
console.log(buf1.toString('utf8', 0, 5));
// 打印: abcde
const buf2 = Buffer.from('tést');
console.log(buf2.toString('hex'));
// 打印: 74c3a97374
console.log(buf2.toString('utf8', 0, 3));
// 打印: té
console.log(buf2.toString(undefined, 0, 3));
// 打印: té
编码和解码-题解:
字符串的base64互转
let baseStr = Buffer.from("my name is cxy").toString('base64');
console.log(baseStr)
baseStr = Buffer.from(baseStr,'base64').toString()
console.log(baseStr)
16进制和字符串互转
let baseStr = Buffer.from("my name is cxy").toString('hex');
console.log(baseStr)
baseStr = Buffer.from(baseStr,'hex').toString()
console.log(baseStr)
将本地图片文件流和base64互转
const fs = require('fs');
// 将本地图片转为base64
function base64_encode(file) {
let bitmap = fs.readFileSync(file);
return new Buffer(bitmap).toString('base64');
}
// 将base64转为本地图片
function base64_decode(base64str, file) {
var bitmap = new Buffer(base64str, 'base64');
fs.writeFileSync(file, bitmap);
}