标准模式/IE模型的区别
CSS如何设置两种模型
JS 如何设置获取盒模型对应的宽和高
1) domElem.style.width/height // 只能取到内联样式的宽和高
2) domElem.currentStyle.width/height // 获取到即时的宽和高,但只有IE支持,通用使用第三种
3) window.getComputedStyle(domElem).width/height
4) domElem.getBoundingClientRect().width/height // 根据视窗,计算元素绝对位置,还可获取top和left
实例:根据盒模型解释边距重叠
BFC(边距重叠解决方案)
<section>
<p>1</p>
<div style="overflow:hidden">
<p>2</p>
</div>
<p>3</p>
</section>
{
margin: 0;
padding: 0;
}
#margin {
background: pink;
overflow: hidden;
}
#margin > p {
background: red;
margin: 5px auto 25px;
}
<section>
<div class="left"></div>
<div class="right"></div>
</section>
{
margin: 0;
padding: 0;
}
#layout {
background: red;
}
#layout .left {
background: pink;
width: 100px;
height: 100px;
float: left;
}
#layout .right {
background: #ccc;
height: 110px;
overflow: auto;
}
<section>
<div>我是浮动元素</div>
</section>
{
margin: 0;
padding: 0;
}
#float {
background: red;
// overflow: auto;
float: left;
}
#float .float {
float: left;
font-size: 30px;
}
创建对象的几种方法
var o1 = {name: 'o1'};
var o11 = new Object({name: 'o11'});
var M = function() {
this.name = 'o2';
}
var o2 = new M();
var P = {name: 'o3'};
var o3 = Object.create(P);
原型链概念
Func.prototpye.constructor === Func; // true
obj.__proto__ === Func.prototype; // true
Func.__proto__ === Function.prototype; // true
instanceof 的原理
new 运算符
// 实现方法 _new,模拟 new 的作用
function _new(f) {
// 返回一个function
return function() {
var obj = {"proto": f.prototype};
f.apply(obj, arguments);
return obj;
}
}
// 测试
function Person(name, age) {
this.name = name;
this.age = age;
}
var pp = _new(Person)("Jialin", 25);
pp instanceof Person; // true;
// 使用 Object.create 模拟 new 方法
var _new2 = function(func) {
var obj = Object.create(func.prototype);
var k = func.call(obj);
if(typeof k === 'object') {
return k;
} else {
return obj;
}
}
借助构造函数实现继承(部分继承)
function Parent() {
this.name = 'parent';
this.arr = [1];
}
function Child() {
Parent.call(this);
this.type = 'child';
}
借助原型链实现继承
function Parent() {
this.name = 'parent';
this.arr = [1, 2, 3];
}
function Child() {
this.type = 'child';
}
Child.prototype = new Parent();
var c1 = new Child();
var c2 = new Child();
console.log(c1.arr); // [1, 2, 3]
c1.arr.push(4);
console.log(c2.arr); // [1, 2, 3, 4]
c1.proto === c2.proto; // true
组合方式
function Parent() {
this.name = 'parent';
this.arr = [1, 2, 3];
}
function Child() {
Parent.call(this);
this.type = 'child';
}
Child.prototype = new Parent();
var cc = new Child();
cc.constructor; // Parent(){...}
function Parent() {
this.name = 'parent';
this.arr = [1, 2, 3];
}
function Child() {
Parent.call(this);
this.type = 'child';
}
Child.prototype = Parent.prototype;
var cc = new Child();
cc.constructor; // Parent(){...}
function Parent() {
this.name = 'parent';
this.arr = [1, 2, 3];
}
function Child() {
Parent.call(this);
this.type = 'child';
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
原型式继承
function object(o) {
function F(){};
F.prototype = o;
return new F();
}
复制代码
寄生式继承
function createAnother(originalObj) {
var clone = object(originalObj);
clone.sayHi = function() {
// ...
}
return clone;
}
DOM事件类
element.onclick = function() {}
// W3C
element.addEventListener('click', function(){}, false);
// IE
element.attachEvent('click', function(){}, false);
element.addEventListener('keyup', function(){}, false);
DOM事件捕获/冒泡过程
Event 对象的常见应用
// IE
event.sourceElement
自定义事件(无需使用回调)
var eve = new Event('custom');
ev.addEventListener('custom', function(){
console.log('custom');
});
// 触发
ev.dispatchEvent(eve);
复制代码
7 种数据类型
显示类型转换
// 原始类型
数值 ==> 原始值
字符串 ==> 数值(空字符为0) or NaN
布尔值 ==> true为1,false为0
undefined ==> NaN
null ==> 0
对象,先调用该对象自身的 valueOf 方法,
var obj = {a:1};
console.log(Number(obj));
其中,
obj.valueOf()返回{a: 1}, {a: 1}的toString()返回'[object Object]'
// 原始类型
数值 ==> 对应字符串
字符串 ==> 原始值
布尔值 ==> true变为'true',false变为'false'
undefined ==> 'undefined'
null ==> 'null'
复合类型,先调用该对象自身的 toString 方法,
// 原始类型
undefined, null, -0, +0, NaN, 空字符串 均转为 false
隐式类型转换
常见题目
[] + [] ==>
[] + {} ==>
{} + [] ==> 0
{} + {} ==> "[object Object][object Object]"
true + true ==>
1 + {a: 1} ==>
同源政策及其限制
补充:cookie,localStorage和sessionStorage区别
复制代码
前后端如何通信
如何创建 Ajax
var xhr = XMLHttpRequest ? new XMLHttpRequest() : new window.ActiveXObject('Microsoft.XMLHTTP');
var data = opt.data;
var url = opt.url;
var type = opt.type.toUpperCase();
var dataArr = [];
for(var k in data) {
dataArr.push(k + '=' + data[k]);
}
if(type === 'GET') {
url = url + '?' + dataArr.join('&');
xhr.open(type, url.replace(/?$/g, ''), true);
xhr.send();
}
if(type === 'POST') {
// 第三个参数:默认为true,表示异步发送
xhr.open(type, url, true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(dataArr.join('&'));
}
xhr.onload = function(){
if(xhr.status === 200 || xhr.status === 304) {
var res;
if(opt.success && opt.success instanceof Function) {
res = xhr.responseText;
if(typeof res === 'string') {
res = JSON.parse(res);
opt.success.call(xhr, res)
}
}
} else {
if(opt.error && opt.error instanceof Function) {
opt.error.call(xhr, res);
}
}
}
// Promise封装
var getJSON = function(url) {
var promise = new Promise((resolve, reject) => {
var client = new XMLHttpRequest();
client.open('GET', url);
client.onreadystatechange = handler;
client.responseType = 'json';
client.setRequestHeader('Accept', 'application/json');
client.send();
function handler() {
if(this.readyState !== 4) {
return;
}
if(this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
});
return promise;
}
跨域通信的几种方式
util.jsonp = function(url, onsuccess, onerror, charset) {
var callbackName = util.getName('name');
window[callbackName] = function() {
if(onsuccess && util.isFunction(onsuccess)) {
onsuccess(arguments[0]);
}
}
var script = util.createScript(url + '&callback=' + callbackName, charset);
script.onload = script.onreadystatechange = function() {
if(!script.readyState || /loaded|complete/.test(script.readyState)) {
script.onload = script.onreadystatechange = null;
if(script.parentNode) {
script.parentNode.removeChild(script);
}
window[callbackName] = null;
}
};
script.onerror = function() {
if(onerror && util.isFunction(onerror)) {
onerror();
}
}
}
//动态创建 script 标签,并请求
function addScriptTag(src){
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.src = src;
document.body.appendChild(script);
};
// 在 onload 后,跨域请求
window.onload = function(){
addScriptTag('http://127.0.0.1:8080/jsonp?callback=test');
};
//回调函数,必须为全局,不然会报错
function test(data){
alert(data.name);
};
server.on('request',function(req, res){
var urlPath = url.parse(req.url).pathname;
var qs = querystring.parse(req.url.split('?')[1]);
if(urlPath === '/jsonp' && qs.callback){
res.writeHead(200,{'Content-Type':'application/json;charset=utf-8'});
var data = {
"name": "Monkey"
};
data = JSON.stringify(data);
var callback = qs.callback+'('+data+');';
res.end(callback);
} else {
res.writeHead(200, {'Content-Type':'text/html;charset=utf-8'});
res.end('Hell World\n');
}
});
// 当前页面A通过iframe嵌入了跨域页面B
// A中:
var B = document.getElementsByTagName('iframe');
B.src = B.src + '#' + 'data';
// B中
window.onhashchange = function() {
var data = window.location.hash;
}
// 窗口A(http://A.com)向窗口B(http://B.com)发送消息
Bwindow.postMessage('data', 'http://B.com');
// 在B窗口中
window.addEventListener('message', function(evet) {
console.log(event.origin); // http://A.com
console.log(event.source); // Bwindow
console.log(event.data); // data
}, false);
var ws = new WebSocket('wss://echo.websocket.org');
ws.onopen = function(evt) {
console.log('Connection open...');
ws.send('Hello WebSockets');
}
ws.onmessage = function(evt) {
console.log('Received Message: ', evt.data);
ws.close();
}
ws.onclose = function(evt) {
console.log('Connection closed.');
}
// 客户端
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
// 服务器端
Access-Control-Allow-Credentials: true补充:fetch API
// url必须,options可选
fetch('/some/url', {
method: 'get',
}).then(function(response) {
}).catch(function(err){
});
- 它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。
- 这类攻击通常包含了HTML以及用户端脚本语言
举例:通过客户端脚本(JS)在一个论坛发帖中发布一段恶意的JS代码就是脚本注入,如果这个代码内容有请求外部服务器,那么就叫做XSS!
防护:
CSRF 跨站请求伪造
- 冒充用户发起请求(在用户不知情的情况下),完成一些违背用户意愿的请求
1.登录受信任网站A,并在本地生成Cookie 。
2.在不退出A的情况下,访问危险网站B。
防护:token防御的整体思路是:
HTTP协议的主要特点
HTTP报文的组成部分
HTTP方法
POST和GET的区别
HTTP状态码
请求1 - 响应1 - 请求2 - 响应2 - 请求3 - 响应3
// 管线化,请求打包发送,依次进行响应(单独),并保持顺序
请求1 - 请求2 - 请求3 - 响应1 - 响应2 - 响应3
https 的介绍
1. HTTP的缺点
- 使用明文(不加密)通信,内容可能被窃听
- 不验证通信方的身份,可能遭遇伪装
- 无法证明报文的完整性,可能已遭篡改
HTTPS 介绍
HTTPS = HTTP + 加密 + 认证 + 完整性保护
1)HTTPS使用SSL,先和SSL通信,再由SSL和TCP通信
补充:
对称密钥加密:加密和解密用同一个密钥的方式(共享)
非对称密钥加密:
2)HTTPS采用混合加密机制
3)证明公开密钥的正确性 --> 使用由数字证书认证机构颁发的公开密钥证书
4)HTTPS还可以使用客户端证书
HTTP 2.0 与 HTTP1.1 的区别
- HTTP/2采用二进制格式而非文本格式
- HTTP/2是完全多路复用的,同时发起无数个请求,并且响应可以同时返回
- 使用报头压缩,HTTP/2降低了开销
- HTTP/2让服务器可以将响应主动“推送”到客户端缓存中
复制代码
3 次挥手 && 4 此握手
DTD 文档类型定义
DOCTYPE
常见的 DOCTYPE:
HTML 5
<!DOCTYPE html>
HTML 4.01 Strict 该DTD包含所有HTML元素和属性,但不包括展示型的和弃用的元素(如:font)
HTML 4.01 Transitional 该DTD包含所有HTML元素和属性,包括展示型和弃用的元素
DocumentFragment:
整个最基本的 Event Loop 如图所示:
task主要包含:setTimeout、setInterval、setImmediate、I/O、UI交互事件
microtask主要包含:Promise、process.nextTick、MutaionObserver
console.log(1)
setTimeout(() => {
console.log(2)
}, 0)
Promise.resolve().then(() => {
console.log(3)
}).then(() => {
console.log(4)
})
console.log(5)
// 1 5 3 4 2
分析如下:
同步运行的代码首先输出:1、5,接着,清空microtask队列:3、4
setTimeout(fn, 0) 的含义
console.log('abc');
setTimeout(() => {
console.log('执行啦')
},3000);setTimeout(() => {
console.log('执行啦123')
},0);
// 'abc'
// 执行啦123
// 执行啦
process.nextTick(callback) 的含义
setTimeout 与 Promise 混合
console.log(1)
setTimeout(() => {
console.log(2)
new Promise(resolve => {
console.log(4)
resolve()
}).then(() => {
console.log(5)
})
})
new Promise(resolve => {
console.log(7)
resolve()
}).then(() => {
console.log(8)
})
setTimeout(() => {
console.log(9)
new Promise(resolve => {
console.log(11)
resolve()
}).then(() => {
console.log(12)
})
});
分析如下:
同步运行的代码首先输出:1、7
接着,清空microtask队列:8
第一个task执行:2、4
接着,清空microtask队列:5
第二个task执行:9、11
接着,清空microtask队列:12
setTimeout,Promise 与 process.nextTick 的混合
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
复制代码
setTimeout 函数中,0ms 和 1ms 的效果一样(结果都是 1ms 后,传入 task 队列)
setTimeout(() => {
console.log(2)
}, 2)
setTimeout(() => {
console.log(1)
}, 1)
setTimeout(() => {
console.log(0)
}, 0)
// 1, 0, 2
使用了缓存后, 更改js文件内容但未更改js文件名。 重新发布后,怎么保证浏览器加载的是最新的js文件?
A:让浏览器上的强缓存事件变短
window.addEventListener('error', (e) => {
console.log('捕获', e);
}, true);
// true表示捕获,false表示冒泡跨域的JS运行错误可以捕获吗?错误提示是什么?应该怎么处理?
跨域错误只提示 Script Error,解决方法:script 标签增加 crossorigin 属性,设置 js 资源响应头为 Access-Control-Allow-Origin: *
(new Image()).src = 'http://...'; 该请求可以直接被发出
写出下面的输出
function Foo() {
getName = function(){console.log(1);}
return this; // 指window对象
}
Foo.getName = function(){console.log(2);}
Foo.prototype.getName = function(){console.log(3);}
var getName = function(){console.log(4);} // 变量定义提升
function getName(){console.log(5);} // 函数定义提升
Foo.getName(); // 2
getName(); // 4
Foo().getName();
// 1,返回window对象,调用window对象的getName方法(已经被从4修改为1)
getName(); // 1
new Foo.getName(); // 2
// 等价于
new function(){console.log(2);}();
new Foo().getName(); // 3
// 等价于
新建一个Foo函数的实例,调用该实例上(或原型上)的getName方法
new new Foo().getName();// 3
// 等价于
new foo.getName();
先执行new Foo(),得到Foo函数的实例;
由于点操作符的优先级高于new(不带参数),故先执行foo.getName(),返回3
数组扁平化
var flag = function(arr) {
let toString = Array.prototype.toString;
Array.prototype = function() {
return this.join(',');
}
// 隐式调用toString()
let result = arr + '';
Array.prototype.toString = toString;
return result;
}
复制代码
Array.prototype.valueOf = function() {
return this.join(',');
}
var flat = function(arr) {
return arr + '';
};
flat(arr);
方法3:[Symbol.iterator] 遍历器
Array.prototype.[Symbol.iterator] = function() {
let arr = [].concat(this);
let getFirst = function(array) {
let first = array.shift();
return first;
}
return {
next: function() {
let item = getFirst(arr);
if(item) {
return {
value: item,
done: false
};
} else {
return {
done: true
}
}
}
}
}
var flat = function(arr) {
let r = [];
for(let i of arr) {
r.push(i);
}
return r.join(',');
}
function flat (arr) {
let jsonArr = JSON.stringify(arr); // 将数组转化成json
return jsonArr.replace(/(\[|\])/g, ''); // 用正则去掉json中所有的中括号并返回
};
flat(arr);
实现如下功能
// 递归实现(深拷贝)
function func(arr, str) {
str = Array.isArray(str) ? str : JSON.parse(str.replace(/([a-z]+)/g, '"$1"'));
let obj = {};
str.forEach((val, index) => {
let res = arr[index];
if(Array.isArray(val)) {
Object.assign(obj, func(res, val))
} else {
obj[val] = res;
}
}}
}

