前端知识总结
- 数据类型
- Proxy
- Promise
- AJAX
- 跨域
- Js循环
- JS对象遍历
- Websocket
- JS中this
- JS原型和原型链
- JS作用域、作用域链、闭包
- JS传参
- 严格模式strict
- JS方法
- JS深拷贝
- 防抖和节流
- js类创建
- 类的继承
- new原理
- http协议
- [JS异步 Event Loop模型](https://segmentfault.com/a/1190000018533261)
- [Node 定时器详解、事件循环机制](http://www.ruanyifeng.com/blog/2018/02/node-event-loop.html)
- DOM事件机制
- 箭头函数
- cookie、sessionStorage、localStorage
- session
- token验证机制
- CSRF攻击
- XSS攻击
- 正则表达式
- 浏览器
- Reflow和Repaint
- 浏览器检测
- !DOCTYPE作用
- 强缓存、协商缓存
- CDN
- DNS解析
- 页面性能能提升方法
- 错误监控
- jQuery获取元素信息
- video标签
- 时间显示NAN
- || 和 && 的返回值
- [URI 和 URL](https://blog.csdn.net/qq_32595453/article/details/80563142)
- URL中的#
- eslint
- 单页面应用SPA
- H5端日历左右滑动效果
- 函数柯里化
- 变量提升
- js连等
- 二进制与十进制转换
- js类型判断
- Generator生成器
- 函数式编程
- JS函数是一等公民
- 前端模块化
- [arrayBuffer, typedArray, dataView](https://www.cnblogs.com/jixiaohua/p/10714662.html)
- js编码
- JS运行机制
- 设计模式
- WebRTC
- 进程与线程
- 进程间通信
- 线程间共享的资源
- clientHeight、offsetHeight、scrollHeight、offsetTop、scrollTop
- SSO单点登录
- DOM元素属性
- JsBridge
- encodeURI和encodeURIComponent
- 移动端屏幕固宽
- 容器部署 pipeline
- Vue多入口项目
- FMP
- 前端请求打散
- 向下滑动加载更多
数据类型
- 基本数据类型
Boolean Number String Null Undefined Symbol Bigint - 复杂数据类型
Object
Proxy
proxy是一个拦截对象实例,target是拦截的目标对象,handler是拦截操作。proxy实例相当于在target对象之上增加了handler操作,实际操作proxy就等于操作target + handler。如果target为空,则proxy也为空。如果handler为空,操作proxy就相当于直接操作target。
var proxy = new Proxy(target, handler);
例如下面代码是将person对象进行包装,使用handler拦截操作,proxy.name就相当于访问person.name,但是在执行.操作读取时重新对get进行定义。get函数中propKey是target对象的属性,就是.之后的你想得到的东西,这里是name。
var person = {
name: 'xiao'}
var handler = {
get(target, propKey, receiver) {
if(propKey in target){
console.log(target[propKey])
}
else{
console.log("wrong")
}
}
}
var proxy = new Proxy(person, handler)
proxy.name
Promise
Promise的作用是实现异步操作,通过new Promise的方式生成一个Promise对象。resolve和reject是由JS提供的函数,他们的作用是改变Promise对象的状态,resolve使对象状态由pending(进行中)变为resolved(成功),reject使对象状态由pending变为rejected(失败)。且一个对象只能存在一种状态,一旦状态改变之后则不能再改变。
若状态为resolved则回调函then之后执行success对应内容,若状态为rejected则执行failure中内容。执行resolve函数后后面的内容仍然会执行,除非return掉。
因为错误具有冒泡的性质,所以错误最终都会被catch捕捉。一般不使用then的第二个参数处理错误,而统一使用catch处理错误。
finally操作无论Promise对象状态是什么最终都会执行,而且不接收参数。
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
promise.then(function(value) {
// success
}, function(error) {
// failure
}).catch(function(error){
//catch
}).finally(() => {
//code
});
setTimeout(fn, 0)在下一轮“事件循环”开始时执行,Promise.then()在本轮“事件循环”结束时执行。因此then 函数先输出,settimeout后输出。
setTimeout(function(){
console.log(1)
},0)
var promise = new Promise(function(resolve, reject){
console.log(2)
resolve()
console.log(3)
})
promise.then(function(){
console.log(4)
})
console.log(5)
output:2 3 5 4 1
Promise 实现原理
AJAX
AJAX(Asynchronous JavaScript and XML)在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
//创建XMLHttpRequest对象
var xmlhttp;
if (window.XMLHttpRequest)
{
// IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
xmlhttp=new XMLHttpRequest();
}
else
{
// IE6, IE5 浏览器执行代码
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
//向服务器发送请求,method规定请求方式'GET'或'POST',url为请求文件在服务器上的位置,
async为bool是否异步,string为POST请求时的携带参数
xmlhttp.open("method","url",async);
xmlhttp.send(string);
//setRequestHeader(header,value)向请求添加http头,header为规定头的名称,value为规定头的值
当使用get时,send(),当使用post时,需要通过send传递参数,在使用send前需要设置请求头部
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Henry&lname=Ford") //string为要发送的数据
在开启异步时需要规定在响应处于 onreadystatechange 事件中的就绪状态时执行的函数,每当readystate变化时触发该函数。
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
服务器响应responseText为字符串形式响应数据,responseXML为XML形式的相应数据。
post和get对比
跨域
跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器施加的安全限制。
JSONP不支持post
所谓同源是指,域名,协议,端口均相同
跨域解决方案:Jsonp、CORS
Js循环
普通for循环不再赘述
- for…in
for in遍历的是对象中的key,如果遍历数组则是遍历索引
var obj1 = {
'a':1, 'b':2}
var obj2 = ['a','b','c']
for(let key in obj1) \\此时key是'a', 'b'
for(let key in obj2) \\此时key是 0, 1, 2
- for…of
for of只能遍历能够迭代的比如数组、map、set、字符串。但是不能遍历对象,因为对象没有迭代器。for of遍历的是其中的值。
var obj = ['a','b','c']
for(let val in obj) \\此时val是'a', 'b'
- forEach
forEach是可以被迭代的对象的成员方法,接受一个参数回调函数callback,回调函数的三个参数(value, key, iterable),(值,键,可以迭代的对象本身),每次循环执行该回调函数。
forEach不能break也不能return提前跳出循环,可以通过抛出异常终止。
var iterable
iterable.forEach(function(val, key, iterable){
})
- Array.map()
for...of
, forEach
, map
中直接修改item不会影响原数组
let arr = [1, 2, 3, 4, 5]
for(let item of arr) {
item += 1
}
arr.forEach(item => {
item += 1
})
arr.map(item => {
item += 1
})
console.log(arr) // [1, 2, 3, 4, 5]
JS对象遍历
对象的属性分为可枚举和不可枚举之分,是由属性的enumerable值决定的
for in
主要用于遍历对象的可枚举属性,包括自有属性、继承自原型的属性Object.keys(obj)
主要用于遍历对象自有的可枚举属性,不包括继承自原型的属性和不可枚举的属性。Object.getOwnPropertyNames(obj)
用于返回对象的自有属性,包括可枚举和不可枚举的属性
Websocket
http://www.52im.net/thread-1341-1-1.html
websocket是一种网络通讯协议,HTTP协议只能由客户端向服务器发送请求而websocket协议中服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息。
websocket特点
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
websocket断线重连
JS中this
https://segmentfault.com/a/1190000011194676
JS原型和原型链
https://blog.csdn.net/u013302153/article/details/53543882
https://www.jianshu.com/p/ae7afb5ba420
一.所有构造器/函数的__proto__都指向Function.prototype(Function.prototype是一个空函数)
函数Function与其他的函数不同,他的prototype和 _ proto _ 都指向Function的原型。
原型是对象
Object.prototype.__proto__ // null
Function.prototype === Function.__proto__ // true
Function.prototype === Object.__protp__ // true
Function.prototype.__proto__ === Object.prototype // true
Function instanceof Object // true
Object instanceof Function //true
let fn = function(){
}
fn instanceof Function // true
JS作用域、作用域链、闭包
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。
词法分析器会在函数执行前分析出变量依赖,从而形成作用域链
(function(){
})()
这种写法就相当于直接执行function
闭包
- 作用
- 保护私有变量不受外界干扰
- 形成不销毁的栈内存,把一些值保存下来方面后面调取使用
JS传参
ECMAScript中所有函数的参数都是按值传递的,当参数为基本类型时,参数arg是将a进行复制。当参数arg为引用类型时,实际上是复制了指针b,此时arg和b指向同一片内存。如果在函数中对arg进行重新赋值一个新的引用类型,那么arg将指向一片新的内存,所以此时改变arg,外部的b不再受影响。
function func(arg){
arg = new String('sakuragi')
}
var a = 3
var b = new String('rukawa')
func(b)
console.log(b) //'rukawa'
严格模式strict
JS方法
instanceof
path.join()
const path = require('path')
path.join('a','/b', 'c') // a/b/c
path.join('/a','b', 'c/') // /a/b/c/ join会自动将缺少的/补全,并且在两端的/会被保留
path.join('a','b','../c') // a/c join支持../向上跳转
path.resolve()
path.resolve([from …], to)
将 to 参数解析为绝对路径,给定的路径的序列是从右往左被处理的
path.resolve('a','b') // /Users/super/webpackExercise/a/b 如果没有指定根目录会自动根据当前文件所在目录补全路径
path.resolve('a','b','../c') // /Users/super/webpackExercise/a/c 支持../向上跳转
path.resolve('a','/b','c') ///Users/super/webpackExercise/b/c 如果从右向左解析过程中出现/根目录则解析完毕
apply,call,bind
apply参数为数组,call和bind参数为一个一个的参数
bind返回的是一个函数,apply和call返回函数调用结果
func.apply(thisArg, [argsArray])
返回调用有指定this值和参数的函数的结果。
function.call(thisArg, arg1, arg2, ...)
返回使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined。
function.bind(thisArg, arg1, arg2, ...)
返回一个原函数的拷贝,并拥有指定的 this 值和初始参数。
apply call bind 原理
Function.prototype.imitateBind = function (context) {
// 获取绑定时的传参
let args = [...arguments].slice(1),
// 定义中转构造函数,用于通过原型连接绑定后的函数和调用bind的函数
F = function () {
},
// 记录调用函数,生成闭包,用于返回函数被调用时执行
self = this,
// 定义返回(绑定)函数
bound = function () {
// 合并参数,绑定时和调用时分别传入的
let finalArgs = [...args, ...arguments]
// 改变作用域,注:aplly/call是立即执行函数,即绑定会直接调用
// 这里之所以要使用instanceof做判断,是要区分是不是new xxx()调用的bind方法
// 当bind返回的函数被当做构造函数进行 new 调用的时候,this不再指向bind绑定的
// 那个对象的作用域,而是指向new的这个新对象的this
return self.call((this instanceof F ? this : context), ...finalArgs)
}
// 将调用函数的原型赋值到中转函数的原型上
F.prototype = self.prototype
// 通过原型的方式继承调用函数的原型
bound.prototype = new F()
return bound
}
function Person (name) {
console.log(this.name)
console.log(arguments)
}
let a = {
name: 'zyx',
}
Person.bind(a, 'ok')('pl') // zyx [Arguments] { '0': 'ok', '1': 'pl' }
此时函数中的this</