标签:轮播 als 完成 css dom节点 子类 round 元素 赞美
答:我平时喜欢研究一些网站,并对一些技术的原理和好玩的点感兴趣,我自己也喜欢思考,也喜欢尝试探索有没有更好的方式和实现。(有所收留,不要全部说出来,稍微留一点悬念留作面试官来提问)
答:适当自信,向自己擅长的方向上面来引路;要让面试官来欣赏我,而不是来鄙视他。
(豁达自信,适当收住),巧妙演示实例,适时讨论疑问(不知道的问题请求指导一下,如何去解决,不要说不知道,或者不了解)
切忌小聪明(尽量把问题的所有实现方法都写出来,表现出来的是熟练)
[!NOTE]
> 1. 方向要对,过程要细(性能优化,过程详细)
> 2. 胆子要大、心态要和(算法题认真思考,认真使劲想;敢于承担责任,不要轻易放弃)
1.已知宽高
/*v1*/
.container {
position: absolute;
left: 50%;
top: 50%;
marigin-left: -width / 2;
marigin-top: -width / 2;
}
/*v2*/
.container {
position: absolute;
top: calc(50% - 5em);
left: calc(50% - 9em);
}
2.未知宽高
/*v1*/
.container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/*v2:flex+ auto*/
.wrapper {
dislay: flex;
}
.content {
margin: auto;
}
/*v3. 父元素居中*/
.wrapper {
display: flex;
/* 盒子横轴的对齐方式 */
justify-content: center;
/* 盒子纵轴的对齐方式 */
align-items: center;
}
/*v4.body内部居中*/
.content {
/* 1vh = 1% * 视口高度 */
margin: 50vh auto;
transform: translateY(-50%);
}
/* 网格布局 */
.wrapper {
display: grid;
width: 100%;
grid-template-columns: 300px 1fr 300px;
}
[!NOTE]
知道transition 过渡动画和animation 关键帧动画区别和具体实现。
- 1.CSS动画实现轮播图
- 2.CSS动画实现旋转的硬币
- 3.CSS动画实现钟摆效果
IE盒子模型:width = content + pading + border
box-sizing : border-box
解决方案:对父级元素创建BFC
[!NOTE]
BFC: 块级格式化上下文,IFC(内联格式化上下文)
<section id="margin">
<style>
#margin {
background-color: #4eff35;
overflow: hidden;
}
#margin>p {
/*上 左右 下*/
margin: 5px auto 25px;
background-color: #ff255f;
}
</style>
<p>1</p>
<!--把一个元素放在一个容器里面,为这个容器创建BFC即可解决边距重叠问题-->
<div style="overflow: hidden">
<p>2</p>
</div>
<p>3</p>
</section>
<section id="layout">
<style>
#layout {
background-color: #48adff;
}
#layout .left {
float: left;
height: 300px;
width: 200px;
background-color: #ff4344;
}
#layout .right {
height: 400px;
background-color: #ff255f;
/*给右边的这个盒子容器创建一个BFC, 这个容器里面的内容就会沿着垂直方向延伸*/
overflow: auto;
/*overflow: auto;*/
/*display: table;*/
/*float: left;*/
/*position: fixed;*/
}
</style>
<div class="left">
LEFT
</div>
<div class="right">
RIGHT
<p>111</p>
<p>111</p>
<p>111</p>
<p>111</p>
<p>111</p>
<p>111</p>
<p>111</p>
<p>111</p>
<p>111</p>
<p>111</p>
<p>111</p>
<p>111</p>
<p>111</p>
<p>111</p>
<p>111</p>
</div>
</section>
<section id="float">
<style>
/*一个盒子内部的内容如果是浮动的话,那么这个盒子的内容实际上是不参与父容器高度计算的*/
#float {
background-color: red;
/*overflow: hidden;*/
float: left;
}
#float .float {
float: left;
font-size: 30px;
}
</style>
<div class="float">
我是浮动的元素
</div>
</section>
[!NOTE]
DOM级别一共可以分为四个级别:DOM0级、DOM1级、DOM2级和DOM3级。而DOM事件分为3个级别:DOM0级事件处理,DOM2级事件处理和DOM3级事件处理。
浏览器为当前的页面与用户进行交互的过程中,点击鼠标后事件如何传入和响应的呢?
什么样的事件可以用事件委托,什么样的事件不可以用呢?
[!NOTE]
- 通常支持事件冒泡(Event Bubbling)的事件类型为鼠标事件和键盘事件,例如:mouseover, mouseout, click, keydown, keypress。
- 接口事件(指的是那些不一定与用户操作有关的事件)则通常不支持事件冒泡(Event Bubbling),例如:load, change, submit, focus, blur。
很明显:focus 和 blur 都属于不支持冒泡的接口事件。既然都不支持冒泡,那又如何实现事件代理呢?
IE采用冒泡型事件 Netscape使用捕获型事件 DOM使用先捕获后冒泡型事件
[!NOTE]
IE DOM
cancelBubble = true stopPropagation() // 停止冒泡
returnValue = false preventDefault() // 阻止元素默认事件
srcEelement target // 事件目标
window -> document -> HTML标签 -> body -> ... -> 目标元素
[!NOTE]
关键点: 注意根节点是window这个对象的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="container">
<style>
#container {
width: 200px;
height: 200px;
background-color: #ff255f;
}
</style>
</div>
<script>
// 事件捕获机制
window.addEventListener('click', function(){
console.log('window capture');
}, true)
document.addEventListener('click', function () {
console.log('document capture');
}, true)
document.documentElement.addEventListener('click', function () {
console.log('HTML capture');
}, true)
document.body.addEventListener('click', function () {
console.log('body capture');
}, true)
document.getElementById('container').addEventListener('click', function () {
console.log('container capture');
}, true)
// 事件冒泡机制
window.addEventListener('click', function(){
console.log('window capture');
})
document.addEventListener('click', function () {
console.log('document capture');
})
document.documentElement.addEventListener('click', function () {
console.log('HTML capture');
})
document.body.addEventListener('click', function () {
console.log('body capture');
})
document.getElementById('container').addEventListener('click', function () {
console.log('container capture');
})
// 输出结果
window capture --> document capture --> HTML capture --> body capture --> container capture --> container capture --> body capture --> HTML capture --> document capture --> window capture
</script>
</body>
</html>
var html = document.documentElement;
document.documentElement.onclick = function(e) {
console.log(e.currentTarget, e.target); // <html><body>...</body></html>()给绑定事件的那个元素, 当前被点击的那个元素
}
[!NOTE]
e.target : 当前被点击的元素,父元素使用事件代理的方式来实现,可以直接使用该属性获取被点击的那个元素
// v1. 使用Event对象来自定义事件
// 开始创建一个自己定义的事件对象
var eve = new Event('customEvent');
// 使用dom2事件处理的方式来给这个元素绑定一个事件
var dom = document.documentElement;
dom.addEventListener('customEvent', function(e) {
console.log('customEvent called!');
});
// 下面的这句话可以在适合的场景中来触发一个自己定义的事件对象
setTimeout(function(){
// 在1s之后触发这个事件
dom.dispatchEvent(eve);
}, 1000)
// v2. 使用CustomEvent来实现自定义事件
var dom = document.documentElement;
// 使用CustomEvent的方式可以在事件触发的时候传递一个参数,然后通过e.detail 的方式来获取这个参数信息
var myClick = new CustomEvent('myClick', {detail : {name : 'zhangsan', age : 24}});
dom.addEventListener('myClick', function(e){
console.log(e.detail, e.target)
})
dom.dispatchEvent(myClick);
[!NOTE]
HTTP协议采用‘请求-应答’模式, HTTP1.1版本才支持的,使用Keep-alive字段可以建立一个长连接,从而不需要每次请求都去建立一个新的连接。
// 1. 使用字面量的方式来创建
var o1 = {name : 'zhangsan'};
var o11 = new Object({name : 'zhangsan'});
// 2. 使用普通构造函数的方式来创建
var M = function(){
this.name = 'zhangsan';
}
var o2 = new M();
// 3. Object.create方法
var p = {name : 'zhangsan'};
var o3 = Object.create(p);
构造函数:使用new运算符来声明一个实例(任何函数都是可以通过构造函数来使用的)
原型链:通过原型链可以找到上一级别的原型对象
原型对象:多个实例公用的数据和属性或者方法
[!NOTE]
instanceof 检测一个对象A是不是另一个对象B的实例的原理是:查看对象B的prototype指向的对象是否在对象A的[[prototype]]链上。如果在,则返回true,如果不在则返回false。不过有一个特殊的情况,当对象B的prototype为null将会报错(类似于空指针异常)。
// 2. 使用普通构造函数的方式来创建
var M = function(){
this.name = 'zhangsan';
}
var o2 = new M();
undefined
o2.__proto__ == M.prototype
true
o2.__proto__ == M.prototype
true
o2.__proto__.constructor === Object
false
o2.__proto__.constructor === M
true
// new 一个对象的过程
var _new = function (fn) {
// 1. 创建一个对象,这个对象要继承fn这个构造函数的原型对象
var o = Object.create(fn.prototype);
// 2. 执行构造函数
var k = fn.call(o, arguments);
// 3. 看下执行的这个函数的运行效果是不是函数
if (typeof k === 'object'){
return k;
}
else
{
return o;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// 类的声明
function Animal1() {
this.name = 'name';
}
// ES6 中的class的声明
class Animal2 {
constructor(){
this.name = 'name';
}
}
console.log(new Animal1(), new Animal2());
///////////////////////////////////////////////////////////////////////////////////////////
// 如何实现类的继承呢???-----------本质:原型链
// v1. 借助构造函数实现继承
function Parent1() {
this.name = 'parent1'
}
Parent1.prototype.sayHello = function () {
console.log('hello');
}
function Child1() {
// 执行父亲的构造函数:
// 1. 实现原理:将父级函数的this指向了这个子类的实例上面去了
// 2. 缺点:父亲的原型链上面的方法或者属性不能被继承;只能实现部分继承
Parent1.call(this);
this.type = 'child1';
}
// 没有参数的时候,可以直接new + 函数名称
console.log(res = new Child1);
// v2. 借助原型链实现继承
function Parent2() {
this.name = 'parent2';
this.data = [1, 2, 3];
}
Parent2.prototype.sayHello = function () {
console.log('hello');
}
function Child2() {
this.type = 'child2';
}
// prototype 就是为了让这个对象的实例可以访问到原型链上的内容
Child2.prototype = new Parent2();
// new Child2().__proto__ === Child2.prototype // true
// new Child2().__proto__.name // parent2
// 原型链继承的缺点:
// 1. 原理:通过修改原型链来实现对象的继承关系
// 2. 缺点:修改第一个对象上面的属性,会直接修改第二个对象属性数据(引用类型)
var c1 = new Child2();
var c2 = new Child2();
c1.data.push(100, 200, 300);
// v3. 组合继承
function Parent3() {
this.name = 'parent3';
this.data = [1, 2, 3];
}
function Child3() {
// 1. 借用构造函数继承
Parent3.call(this);
this.type = 'child3';
}
// 2. 原型链继承
// child3的原型对象是Parent3的一个实例对象,但是这个实例对象中是没有constructor这个属性的,因此寻找属性的时候回沿着这个实例对象的原型链继续向上寻找new Parent3().prototype 这个原型对象的,
// 最终在Parent3.prototype这个原型对象中找到了这个属性,new一个对象找的实际上是{Parent3.prototype.constructor : Parent3}
Child3.prototype = new Parent3();
var c1 = new Child3();
var c2 = new Child3();
c1.data.push(100, 200, 300);
// 组合继承的特点:
// 1. 原理:结合借用构造函数继承和原型链继承的优点,摒弃二者的缺点
// 2. 缺点:父类构造函数在创建实例的时候总共执行了两次(new Parent3(), new Child3())
// v4. 组合继承的优化1
function Parent4() {
this.name = 'parent4';
this.data = [1, 2, 3];
}
function Child4() {
// 1. 借用构造函数继承
Parent4.call(this);
this.type = 'child4';
}
// 让子类的构造函数的原型对象和父类构造函数的原型对象执向同一个对象(都是同一个对象)
Child4.prototype = Parent4.prototype;
// 测试
var c1 = new Child4();
var c2 = new Child4();
console.log(c1 instanceof Child4, c1 instanceof Parent4);
console.log(c1.constructor) // Parent4? 如何实现:c1.constructor(c1.__proto__.constructor) === Child4 呢?
// 缺点:
// 1. 无法通过原型对象的constructor属性来获取对象的属性对应的构造函数了(子类和父类公用的是一个contructor)
// 2. obj instanceof Child4 === true; obj instanceof Parent4 === true
// 3. obj.__proto__.constructor === Child4; obj.__proto__.constructor === Parent4 ???
// v5. 组合继承的优化2【完美写法】
function Parent5() {
this.name = 'parent5';
this.data = [1, 2, 3, 4, 5];
}
function Child5(){
Parent5.call(this);
this.type = 'child5';
}
// 通过创建中间对象的方式来把两个对象区分开
// var obj = new Object(); obj.__proto__ = Constructor.prototype;
// 1. Object.create创建的对象obj, 这个obj的原型对象就是参数
// 2. Child5的原型对象是Child5.prototype
// 3. Child5.prototype = obj,obj这个对象相当于就是一个中间的桥梁关系
Child5.prototype = Object.create(Parent5.prototype);
// 当前的方式还是会按照原型链一级一级向上寻找的, 给Child5的原型对象上面绑定一个自己定义的constructor属性
Child5.prototype.constructor = Child5;
// var s1 = new Child5()
// 上面的代码等价于
var obj = Object.create(Parent5.prototype); // obj.prototype = Parent5.prototype
Child5.prototype = obj;
Child5.prototype.constructor = Child5;
// 1. 对象之间就是通过__proto__ 属性向上寻找的
// 2. 寻找规则: child5 ---> Child5.prototype ---> obj(Object.create(Parent5.prototype)) ---> Parent5.prototype
// 技巧:不要让面试官问太多题目:拖拉时间【挤牙膏】,把一个问题尽量吃透
// 消化这一块内容
</script>
</body>
</html>
[!WARNING]
面试技巧
[!NOTE]
同源策略限制是从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。(一个源的文档或脚本是没有权利直接操作另外一个源的文档或脚本的)
function ajax(params){
// 1. 创建对象,考虑兼容性【重点】
var xhr = XMLHTTPRequest ? new XMLHTTPRequest() : new window.ActiveXObject('Microsoft.XMLHTTP'); // *** 兼容性问题必须考虑
// 2. 打开连接
var type = params.type || 'GET',
url = params.url || '',
data = params.data || {},
success = params.success,
error = params.error,
dataArr = [];
for (var k in data) {
dataArr.push(k + '=' + data[k]);
}
//带上Cookie
xhr.withCredentials = true;
if (type.toUpperCase() === 'GET') {
// get
url += '?' + dataArr.join('&');
// 问号结尾的话,直接替换为空字符串
xhr.open(type, url.replace(/\?$/g, ''), true);
// GET 请求的话,是不需要再send方法中带上参数的
xhr.send();
}
else {
// POST
xhr.open(type, url, true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
// POST 请求需要把数据放在send方法里面, data = name=zhangsna&age=18&sex=male
xhr.send(dataArr.join('&'));
}
// 开始监听变化
xhr.onreadystatechange = function(){
// 这里需要考虑强缓存和协商缓存的话直接处理,206是媒体资源的创建方式
if (xhr.readyState === 4 && xhr.status === 200 || xhr.status === 304) {
var res;
if (success instanceof Function) {
res = xhr.responseText;
if (typeof res === 'string') {
res = JSON.parse(res);
// 开始执行成功的回调函数
success.call(xhr, res);
}
} else {
if (error instanceof Function) {
// 失败的话直接返回这个responseText中的内容信息
error.call(xhr, res);
}
}
}
}
}
function jsonp(url, onsuccess, onerror, charset){
// 1. 全局注册一个callback
var callbackName = 'callback' + Math.random() * 100;
window[callbackName] = function(){
if (onsuccess && typeof onsuccess === 'Function') {
onsuccess(arguments[0]);
}
}
// 2. 动态创建一个script标签
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
charset && script.setAttribute('charset', charset);
script.setAttribute('src', url);
script.async = true;
// 3. 开始监听处理的过程
script.onload = script.onreadystatechange = function(){
if (!script.readyState || /loaded|complete/.test(script.readyState)) {
// 4. 成功之后移除这个事件
script.onload = script.onreadystatechange = null;
// 删除这个script的DOM对象(head.removeChild(script), 这个DOM节点的父节点相当于是head标签这个父节点)
script.parentNode && script.parentNode.removeChild(script);
// 删除函数或变量
window[callbackName] = null;
}
}
script.onerror = function(){
if (onerror && typeof onerror === 'Function') {
onerror();
}
}
// 5. 开始发送这个请求(把这个标签放在页面中的head标签中即可)
document.getElementsByTagName('head')[0].appendChild(script);
}
hash 改变后页面不会刷新的
[!NOTE]
使用场景:当前的页面A通过iframe或者frame嵌入了跨域的页面
// 1. A页面中的代码如下
var B = document.getElementsByTagName('iframe');
B.src = B.src + '#' + JSON.stringfy(data);
// 2. B中的伪代码如下
window.onhashchange = function(){
var data = window.location.hash; // 接受数据
data = JSON.parse(data);
}
[!NOTE]
使用场景: 可以实现窗口A(A.com)向窗口B(B.com)发送信息
// 1. 窗口B中的代码如下
var BWindow = window;
BWindow.postMessage(JSON.stringfy(data), 'http://www.A.com');
// 2. 窗口A中代码
var AWindow = window;
AWindow.addEventListener('message', function(e){
console.log(e.origin); // http://www.B.com
console.log(e.source); // BWindow
e.source.postMessage('已成功收到消息');
console.log(JSON.parse(e.data)); // data
}, false)
// 父窗口给子窗口发信息,需要用iframe的contentWindow属性作为调用主体
// 子窗口给父窗口发的信息需要使用window.top,多层iframe使用window.frameElement
[!NOTE]
不受同源策略影响,可以直接使用
var ws = new window.WebSocket('ws://echo.websocket.org');
// 打开连接
ws.onopen = function(e){
console.log('Connection open ……');
ws.send('Hello WebSocket!');
}
// 接受消息
ws.onmessage = function(e){
console.log('Received Message : ', e.data);
}
// 关闭连接
ws.onclose = function(e){
console.log('Connection closed');
}
支持跨域通信版本的Ajax,是一种新的标准(Origin头)【ajax的一个变种,适用于任何】
http://www.ruanyifeng.com/blog/2016/04/cors.html
fetch('/get/name', {
method : 'get'
}).then(function(response){
console.log(response);
}).catch(function(err){
// 出错了;等价于then的第二个参数
});
// 原因:浏览器默认会拦截ajax请求,会根据头中的origin消息进行判断处理消息;Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
Access-Control-Allow-Origin: http://api.bob.com // 必需的字段
Access-Control-Allow-Credentials: true // 可选字段: 是否允许发送cookie
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
CSRF: 跨站请求伪造,Cross site request forgery
XSS: cross-site scripting, 跨站脚本攻击
攻击原理: 注入JS脚本
防御措施: 让JS代码无法解析执行
[!NOTE]
[!NOTE]
算法攻略:多刷题才是硬道理!!!
<!--HTML5的写法-->
<DOCTYPE html>
<!-- HTML 4.01 Strict
1. 这个DTD 包含所有的HTML元素和属性
2. 但是不包含展示性的和弃用的元素(比如font)
-->
<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd" >
<!-- HTML 4.0.1 Transitional
1. 这个DTD 包含所有的HTML元素和属性
2. 也包含展示性的和弃用性的元素(比如font)
-->
<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " http://www.w3.org/TR/html4/loose.dtd" >
[!NOTE]
在W3C标准出来之前,不同的浏览器对页面渲染有不同的标准,产生了一定的差异。这种渲染方式叫做混杂模式。在W3C标准出来之后,浏览器对页面的渲染有了统一的标准,这种渲染方式叫做标准模式。<!DOCTYPE>不存在或者形式不正确会导致HTML或XHTML文档以混杂模式呈现,就是把如何渲染html页面的权利交给了浏览器,有多少种浏览器就有多少种展示方式。因此要提高浏览器兼容性就必须重视<!DOCTYPE>
[!NOTE]
严格模式和混杂模式都是浏览器的呈现模式,浏览器究竟使用混杂模式还是严格模式呈现页面与网页中的DTD(文件类型定义)有关,DTD里面包含了文档的规则。比如:loose.dtd
[!NOTE]
定义:DOM结构中每个元素都有自己的盒子模型,这些都是需要根据各种样式来计算并根据计算结果将元素放在它该出现的位置,这个过程就是reflow;
[!NOTE]
定义:当各种盒子的位置、大小以及其他属性,例如颜色、字体大小都确定下来以后,浏览器于是便按照元素各自的特性绘制了一遍,于是页面的内容出现了,这个过程就是repaint
var frag = document.createDocumentFragment();
frag.appendChild(dom); /*每次创建的节点先放入DocumentFragment中*/
document.getElementById("d1").style.cssText = "color:red; font-size:13px;";
[!NOTE]
对于Layout属性中非引用类型的值(数字型),如果需要多次访问则可以在一次访问时先存储到局部变量中,之后都使用局部变量,这样可以避免每次读取属性时造成浏览器的渲染。
var width = el.offsetWidth;
var scrollLeft = el.scrollLeft;
[!NOTE]
在元素的position为static和relative时,元素处于DOM树结构当中,当对元素的某个操作需要重新渲染时,浏览器会渲染整个页面。将元素的position设置为absolute和fixed可以使元素从DOM树结构中脱离出来独立的存在,而浏览器在需要渲染时只需要渲染该元素以及位于该元素下方的元素,从而在某种程度上缩短浏览器渲染时间。
Layout属性包括:
看代码,写结果?
// 同步任务
console.log(1);
// 异步任务要挂起
setTimeout(function(){
console.log(2)
}, 0);
console.log(3)
// out : 1 3 2
console.log('A');
setTimeout(function(){
console.log('B')
}, 0);
while (true) {
}
// out : A
for (var i = 0; i < 4; i++) {
// setTimeout , setInterval 只有在时间到了的时候,才会把这个事件放在异步队列中去
setTimeout(function(){
console.log(i);
}, 1000);
}
// out : 4 4 4 4
[!NOTE]
JS是单线程的,浏览器引擎会先来执行同步任务,遇到异步任务之后,会把当前的这个异步任务放在time模块中,等到主线程中的所有的同步任务全部执行完毕之后;然后当前的这个异步任务只有时间到了之后,才会把这个任务(回调函数)放在一个异步队列中;当当前的任务栈中的任务全部执行完毕了之后,会先去执行微任务队列中的任务(Promise),然后等到微任务队列中的所有任务全部执行完毕之后,再去执行process.nextTick()这个函数,等到这个函数执行完毕之后,本次的事件轮训结束;
开启新的执行栈,从宏任务队列中依次取出异步任务,开始执行;每个宏任务执行都会重新开启一个新的任务执行栈
什么时候向这个任务队列中放入新的异步任务
理解与放入到异步任务队列的时机
预解析DNS:DNS Prefetch 是一种DNS 预解析技术,当你浏览网页时,浏览器会在加载网页时对网页中的域名进行解析缓存,这样在你单击当前网页中的连接时就无需进行DNS的解析,减少用户等待时间,提高用户体验。(提前解析域名,而不是点击链接的时候才去进行DNS域名解析,可以节省DNS解析需要耗费的20-120毫秒时间)
<!-- https协议的网站,默认是关闭了DNS的预解析的,可以使用下面的语句开启 -->
<meta http-equiv="x-dns-prefetch-control" content="on">
<!-- 开始配置需要进行DNS预解析的域名 -->
<link rel="dns-prefetch" href="//www.zhix.net"> <!--支持http和HTTPS-->
<link rel="dns-prefetch" href="http://bdimg.share.baidu.com" /> <!--支持http的协议-->
<link rel="dns-prefetch" href="http://nsclick.baidu.com" />
<link rel="dns-prefetch" href="http://hm.baidu.com" />
<link rel="dns-prefetch" href="http://eiv.baidu.com" />
var script = document.createElement('script');
document.getElementsByTagName('head')[0].appendChild(script);
// 没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。
<script src="script.js"></script>
<!-- 有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。 -->
<script defer src="myscript.js"></script>
<!-- 有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。 -->
<script async src="script.js"></script>
[!NOTE]
- defer是在HTML解析完成之后(DOMContentLoaded事件执行之后)才会执行,如果是多个,会按照加载的顺序依次执行(按照顺序执行)
- async是在加载完之后立即执行,如果是多个,执行顺序和加载顺序无关(与顺序无关)
[!NOTE]
缓存目的就是为了提升页面的性能
直接从本地读取,不发送请求
Response Headers
cache-control: max-age=315360000(相对时间,优先级比expires高)
expires: Sat, 10 Mar 2029 04:01:39 GMT(绝对时间)
问一下服务器,这个文件有没有过期,然后再使用这个文件
Response Headers
last-modified: Tue, 12 Mar 2019 06:22:34 GMT(绝对时间)
etag: "52-583dfb6f4de80"
向服务器请求资源的时候,带上if-Modified-Since或者if-None-Match这个请求头,去询问服务器:
Request Headers
if-Modified-Since: Tue, 12 Mar 2019 06:22:34 GMT
if-None-Match: "52-583dfb6f4de80"
// 方法一:使用try catch捕获
try {
// ...
} catch (e) {
// error
} finally {
// handle error
}
// 方法二:使用window.onerror 捕获错误
// 无法捕获到资源加载错误
window.onerror = function(msg, url, line, col, error){
// ...
}
window.addEventListener('error', function(msg, url, line, col, error){
// ...
})
// 方法一: 直接在script, img这些DOM标签上面直接加上onerror事件
Object.onerror = function(e){
// ...
}
// 方法二:window.performace.getEntries(间接获取资源加载错误的数量)
var loadedResources = window.performance.getEntries(); // 1. 获取浏览器中已经加载的所有资源(包括各个阶段的详细加载时间)
var loaderImgs = loadedResources.filter(item => {
return /\.jpg|png|gif|svg/.test(item.name)
});
var imgs = document.getElementsByTagName('img'); // 2. 获取页面中所有的img集合
var len = imgs.length - loaderImgs.length; // 3. 加载失败的图片数量
console.log('图片加载失败数量:', len, '条');
// 方法三: 使用事件捕获的方式来实现Error事件捕获
// 使用事件捕获的方式来实现资源加载错误的事件的捕获:window ---> document --> html --- > body ---> div ---...
window.addEventListener('error', function (msg) {
console.log(msg);
}, true);
// 使用事件捕获的方式来实现
window.addEventListener('error', function (msg) {
console.log('资源加载异常成功捕获:', msg);
}, true);
// 使用事件冒泡的方式是只能捕获到运行的时候的一些异常
window.addEventListener('error', function (e) {
console.log('运行异常成功捕获1:', e.message, e.filename, e.lineno, e.colno, e.error);
}, false);
// 这种方式是可以按照参数的方式来接受相关的参数信息
window.onerror = function (msg, url, line, col, error) {
console.log('运行异常成功捕获2:', msg, url, line, col, error);
}
errorinfo :
Script0 error
0 row
0 col
<!-- script 表情添加crossorigin属性 -->
<!-- 除了 script,所有能引入跨域资源的标签包括 link 和 img 之类,都有一样的属性 -->
<script crossorigin src="http://www.lmj.com/demo/crossoriginAttribute/error.js"></script>
// 服务器可以直接设置一个响应头信息
res.setResponseHeader('Access-Control-Allow-Origin', 'www.lmj.com');
// 下面的两种方式都是可以实现错误信息的上报功能的
(new Image).src = 'http://www.baidu.com?name=zhangsna&age=18&sex=male'
(new Image()).src = 'https://www.baidu.com?name=zhangsan'
// IE 浏览器提供的获取电脑硬件的API
var locator = new ActiveXObject ("WbemScripting.SWbemLocator");
var service = locator.ConnectServer(".");
var properties = service.ExecQuery("SELECT * FROM Win32_Processor");
[!NOTE]
可以参考性能优化章节-performance性能监控一文内容。
[!NOTE]
[!NOTE]
主要考察点:乐观积极、主动沟通、逻辑顺畅、上进有责任心、有主张,做事果断、职业竞争力、职业规划
业务能力:可以做到行业第一
思考能力:对同一件事可以从不同角度去思考,找到最优解
学习能力:不断学习新的业务,沉淀、总结
无上限的付出:对于无法解决的问题可以熬夜、加班
目标是什么:在业务上成为专家,在技术上成为行业大牛
近阶段的目标:不断的学习积累各方面地经验,以学习为主
长期目标:做几件有价值的事情,如开源作品、技术框架等
方式方法:先完成业务上的主要问题,做到极致,然后逐步向目标靠拢
标签:轮播 als 完成 css dom节点 子类 round 元素 赞美
原文地址:https://www.cnblogs.com/fecommunity/p/11908984.html