-
头等函数
函数可以当做变量来传参、返回、赋值
-
原型编程
面向对象编程的一种风格,这种风格不会显式的定义类,而是通过给对象添加属性和方法来创建类,甚至可以采用空对象创建类
-
修饰
- async 异步加载,用在js代码与html和其他js无关的情况
- defer 在页面解析完后,按顺序
-
扩展原型链的方法
-
通过new方法创建对象,设置prototype
-
通过Object.create([原型对象], {property:{value: }})函数创建对象,在设置prototype
-
通过Object.setPrototypeOf(obj, prototype)函数给已经存在的对象修改原型对象, 在设置prototype
*这个函数有返回值为添加原型对象后的对象。
这个方法表现不好,动态设置原型干扰了浏览器的优化,
-
创建对象采用
{ property: value, __proto__:{ .... } }
*表现不好,理由和3一样
-
-
字面量
- 数组字面量
- 布尔字面量
- 整数字面量
- 浮点数字面量
- 字符串字面量(模板字符串)
- 对象字面量:属性值得字面量可以使字符串也可以是数字或者是标识符
- 正则字面量
-
闭包
- 定义在内部的函数可以访问外部函数所有的参数和函数,包括外部函数能访问的参数和变量。
- 当内部函数生存周期大于外部函数的时候,内部函数访问的变量会和内部函数绑定在一起,只有通过内部函数才能访问。
-
函数
-
参数
- arguments类数组获得参数列表
- 可以设置默认参数
- 剩余参数语法为 ...args ,args是数组
-
绑定函数
-
将函数的this绑定到特定的对象上,以至于不需要每次都调用call函数并指定对象。
let obj = { x: 2, getX: function(){ return this.x; } } let getXfunc = obj.getX; getXfunc.bind(obj); getXfunc(); //return 2
-
绑定固定的参数
-
配合window.setTimeout(this.function.bind(this), 1000);
-
-
-
继承
-
通过原型链
- 缺点:
- 引用类型数据被所有子类共享
- 创建子类的时候不能向超类的构造函数中传递参数
- 缺点:
-
通过class
- 类声明不会被提前
-
通过借用构造函数
call([obj], args...)
缺点:
- 不能复用函数
- 不能复用父类原型上的属性
function Parent(name, age){ this.name = name; this.age = age; } function Child(name, age, sex){ Parent.call(this, name, age); this.sex = sex; }
-
组合继承
两次调用父类的构造函数
-
原型式继承
Object.create(prototype, {property:{value: ""}})
缺点:引用型数据会共享值
-
寄生式继承
在函数中调用create函数,然后再添加属性,最后返回对象
无法实现函数复用
-
寄生组合式
function Person(name){ this.name = name; } Person.prototype.greeting = function(){ console.log(this.name); } function Student(id,name){ Person.call(this, name); this.id = id; } Student.prototype = Object.create(Person.prototype); Student.prototype.constructor = Student;
-
-
Data
-
Data() 仅返回当前日期(string),不受参数影响;new Date()返回对象,拥有很多方法
-
参数
- 空参数
- 字符串:月 日,年 时:分:秒
- 参数列表:年月日[时分秒]
-
函数
-
getTime() 获得毫秒数
-
getMonth() 获得月份 0-11
-
getDay() 获得星期
-
getFullYear()
-
getHours()
-
getMinutes()
-
getSeconds()
-
Date.parse(string) 返回毫秒数
-
-
正则表达式
-
*: 0 个 或者多个 {0,}
-
+:{1, }
-
?: {0, 1} 当用在量词后面,则采用非贪婪的方式
-
^: 开始
-
$: 结束
-
. :除了换行符以外的单个字符
-
x(?=y) :匹配仅当x后面跟着y的x
-
(?<=y)x: 匹配x前面是y的x
-
x(?!y): 不跟着y的x
-
(?<!y)x: x前面没有y
-
[].filter(t=>/.../.test(t))
-
//.exec('') 返回匹配的字符串 和index
-
string.match(/.../)
-
-
Array
-
forEach(function(){})
-
concat(arg1,arg2..) 返回增加后的数组
-
join("-")
-
push(arg1,arg2) 在原数组上添加,返回数组长度[在原函数上]
-
pop() 从数组的最后删除元素,返回弹出的元素[在原函数上]
-
shift() 移除数组的第一个,返回该元素[在原函数上]
-
unshift(arg1, arg2) 从头添加一个或者多个[在原函数上]
-
splice(index, num, ...args)[在原函数上]
-
slice(begin, end)
-
sort(func) [在原函数]
-
indexOf(elem, begin) 从begin以后第一次出现elem的下标
-
lastIndexOf(elem, from) 从end开始
-
map(func, thisobj) 返回值覆盖原元素[在原函数上]
-
every(func, thisobj) func返回bool,判断每个元素是否都满足func
-
some(func, thisobj) 只要有一个
-
filter(func, thisobj) 返回为true的所有元素
-
reduce(callback, initialvalue), 两两执行操作
//1. 判断this是否为null、 callback是否为function //2. 获得长度值 >>> 0 //3. 初始化value //4. 逐个计算,返回最终结果 if(!Array.prototype.reduce){ Object.defineProperty(Array.prototype, 'reduce',{ value: function(callback/*,initial*/){ if(this === null){ throw new TypeError("reduce is called on null or undefined"); } if(typeof callback !== "function"){ throw new TypeError("callback is not function"); } let obj = Object(this); let length = obj.length >>> 0; let value; let index = 0; if(arguments.length >= 2){ value = arguments[1]; }else{ while( index < length && !(index in obj)){ ++index; } if(index >= length){ throw new TypeError("Empty Array"); } value = obj[index++]; } while(index < length){ if(index in obj){ value = callback(value,obj[index], index, obj); } ++index; } return value; } }) }
-
reduceRight(callback, initialvalue),从右到左
-
可以采用Array.prototype.forEach.call(arguments, function(args){})
-
-
Map
- set('', '') 、get('')、size、has('')、delete('')、clear()
- Object 和Map的比较
- Object的所有键都是string、Map的键是任意的
- Object的size需要手动计算、Map不需要
- Map的遍历顺序就是插入的顺序
- object有原型所以有缺省的键
-
对象
-
Object.getOwnPropertyNames(o),返回所有属性,包括非枚举属性(不包括原型链上的属性)
-
Object.keys(o) 返回所有枚举属性(不包括原型链上的属性)
-
for..in 访问所有枚举属性(包括原型链上的)
-
get、set
{ get func(){ }, }
-
Object.defineproperties(obj, {
"name": {
get: function() {},
set: function(){}
}
})
-
Promise
-
promise是一个对象,用来表示异步操作的成功或者失败,他可以解决函数调用地狱的问题,在异步操作之后返回promise对象,在这个对象上绑定回调函数
-
3种状态:待定、已兑现、已拒绝
-
已决议状态:任何不是通过throw终止,创建已决议状态
已拒绝状态: 通过throw终止,创建已拒绝状态
-
Promise.All(iterableObj)
- 当iterableObj为空,返回resolved的promise
- 当iterable中不包含promise对象,则返回异步完成的promise对象
- 否则当所有promise都完成后,返回已完成,返回所有成功结束promise的数据数组,或者有一个被拒绝,返回被拒绝promise
-
Promise.race(iterableObj)
- 一旦有一个promise对象判定结果,就直接返回相应的promise对象
//define three status const Panding = "panding"; const Fulfilled = "fulfilled"; const Rejected = "rejected"; //define Promise function Promise(executor){ // define property let self = this let state = Panding; let onFulfilled = []; let onRejected = []; //define resolve function function resolve(value){ if(self.state === Panding){ self.state = Fulfilled; self.value = value; self.onFullfilled.forEach(fn=>fn()); } } //define reject function function reject(reason){ if(self.state === Panding){ self.state = Rejected; self.reason = reason; self.onRejected.forEach(fn=>fn()); } } //exec executor try{ executor(resolve, reject); }catch(e){ reject(e); } } //define then function Promise.prototype.then = function (onFulfilled, onRejected){ //prepare resolve and reject function onFulfilled = typeof onFulfilled === "function" ? onFulfilled: onFulfilled=>onFulfilled; onRejected = typeof onRejected === "function" ? onRejected: onRejected=>onRejected; let self = this; //new Promise, call suitable function let promise2 = new Promise(function(resolve, reject){ if(self.state === Fulfilled){ settimeout(()=>{ try{ let x = onFulfilled(self.value); resolvePromise(promise2, x, resolve, reject); }catch(e){ reject(e); } }); }else if(self.state === Rejected){ settimeout(()=>{ try{ let x = onRejected(self.reason); resolvePromise(promise2, x, resolve, reject); }catch(e){ reject(e); } }); }else if(self.state === Panding){ self.onFulfilled.push(()=>{ settimeout(()=>{ try{ let x = onFulfilled(self.value); resolvePromise(promise2, x, resolve, reject); }catch(e){ reject(e); } }); }); self.onRejected.push(()=>{ settimeout(()=>{ try{ let x = onRejected(self.reason); resolvePromise(promise2, x, resolve, reject); }catch(e){ reject(e); } }) } }) //return Promise return promise2; } //define resolvePromise Function function resolvePromise(promise2, x, resolve, reject){ let self = this; if(promise2 === x){ reject("chaining circle"); } if(x&& typeof x === "object" || typeof x === "function"){ let used; try{ let then = x.then if(typeof then === "function"){ then.call(x, (t)=>{ if(used) return; used = true; resolvePromise(promise2, y, resolve, reject); }, (e)=>{ if(used) return; used = true; reject(e); }) }else{ if(used) return; used = true; resolve(x); } }catch(e){ if(used) return; used = true; reject(e); } }else{ resolve(x); } } //export module module.exports = Promise;
Promise.all = function(promises){ return new Promise(function(resolve, reject){ let result = [] if(promises.length === 0){ resolve(result); } let pending = promises.length; let callPromise = function(i){ promises[i].then(value=>{ result.push(value); if(!--pending){ resolve(result); } },reject); } let i = promise.length; while(i--){ callPromise(i); } }) } Promise.race = function(promises){ return new Promise(function(resolve, reject){ promises.forEach(promise=>{ promise.then(resolve, reject); }) }) }
-
-
async/await
-
async function(){ try{ let value = await promise; }catch(errorValue){ } }
-
-
AJAX
-
httpRequest 不能在全局作用域使用,他会在makeRequest()函数中被覆盖从而导致资源覆盖
-
(function(){ let httpRequest = new XMLHttpRequest(); httpRequest.onreadystatechange = func; http.open('GET','url'); httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); http.send(""); function func(){ try{ if(httpRequest.readyState === XMLHttpRequest.DONE){ if(httpRequest.state === 200){ alert(httpRequest.responseText); }else{ alert("There was a problem"); } } }catch(e){ console.log(e.description); } } })()
-
-
事件:
鼠标事件(click、dbclick、mouseenter、mouseleave)
键盘事件:(keypress、keydown、keyup)
表单事件:focus、blur、change、submit
window事件: load、resize、scroll、unload
-
jquery
-
效果
fadeIn(speed,callback);
fadeOut(speed, callback);
fadeToggle(speed, callback);
fadeTo(speed, opacity,callback);
slidedown(speed,callback)
slideUp(speed, callback)
slideToggle(speed,callback)
animate({param},speed,callback)// 多个animate可以逐个调用
stop()// 停止效果和animate
-
操作html
-
text() 、html()、val()
没有参数那么为get,设置参数或者或者参数是callback,那么为set
callback(index, old){
return new;
}
-
attr({keystr:valuestr});
attr(keystr, callback); //callback(index, old){
return new;
}
-
插入元素
append(htmlstr,...); //在元素内部的尾部插入
prepend(htmlstr, ....) // 在元素内部的首部插入
before(htmlstr)
after(htmlstr);
-
创建元素
$("").html("text");
document.createElement("text").innerhtml = text;
-
删除元素
- remove(arg, ..) // 删除本元素和所有子元素(arg选择)
- empty() // 删除本元素内所有子元素
-
操作样式
-
addClass("classname1 classname2")
-
removeClass("classname")
-
toggleClass("classname");
-
css("cssproperty"); // get
css("cssproperty", "value");//set
css({"cssproperty": "value"});
-
-
元素宽高
- width()、innerWidth() 、outerWidth()、outerWidth(true)
-
-
遍历dom树
- parent()直系父元素
- parents(arg)所有父元素,args是filter
- parentsUntil(arg)
- children() 直系所有子元素
- find(”fiter“) 所有后代元素
- siblings('filter')
- next()
- nextAll('p');
- nextUntil('');
- first()、last()、eq(index),filter("选择器") 、not("选择器")
-
AJAX
-
$.get(url, function(data, status){
})
-
$post(url, param, functon(data, status))// status 可能是success也可能是error
-
-
-
Vue
-
双向绑定的原理:采用数据劫持和发布订阅模式。数据劫持采用js中Object.defineProperty实现,将数据转化成getter和setter,在setter中通知订阅者
在Complie中对每个节点中指令解析更具指令模板替换数据以及绑定函数
watcher作为连接Watcher和Compile的桥梁,用于发布属性更新的通知,执行回调函数,更新视图。
-
MVVM:核心部件是ViewModel,他对Model中的数据进行绑定,对VIew中的Dom进行监听。当Dom中的数据或者Model中的数据变化的时候能实时一起更改。从而达到数据的双向绑定
-
-
浏览器缓存机制:
-
缓存的位置
- Service Work。是浏览器背后独立运行的线程,由于需要拦截请求,用在https请求中。他和其他浏览器内置的缓存机制不同,可以规定缓存什么数据,如何匹配、如何获取。缓存的流程是:获得service对象,监听到install事件的时候,缓存文件,下次请求相同文件的时候,拦截请求,查看时候有匹配的文件,有的话就返回,没有的话就去按照优先级请求。
- Memory cache是内存中的缓存,当Tab标签页关闭的时候,缓存就会消失,这种缓存不会受到http缓存头cachecontrol的影响,缓存的时候除了考虑url,还考虑content-type、cors等
- disk cache。缓存在硬盘中,根据http缓存头来确定是否缓存、是否更新
- Push cache。存在于http2中,只在session中存在,会话结束就会被释放
-
缓存机制:强缓存优先于协商缓存。当强缓存生效的时候,采用强缓存,强缓存失效,使用协商缓存,由服务器决定是否使用缓存,协商缓存生效,返回304,使用缓存,失效返回200,并更新文件
-
强缓存:不会向浏览器发送请求,从缓存中请求文件
- 设置方法:
- expires:需要和last-modified配合使用,值为max-age+服务器时间 。http1的产物。
- cache-control:
- public:允许代理和客户端缓存
- private:只允许客户端缓存
- max-age=30: 在一段时间内使用强缓存
- s-max-age=30:覆盖max-age(只在代理服务器中生效)
- max-stale=30:能够容忍最大的过期时间
- min-fresh=30: 时间内希望获得最新响应
- no-store:不缓存
- no-cache:缓存但是立刻过期,下一次请求的时候需要请求服务器是否使用缓存,也就是协商缓存(Etag、lastModified)
- 设置方法:
-
协商缓存:强缓存失效后,浏览器携带缓存标识向服务器发送请求。协商生效返回304、Not Modified,协商成功返回200和请求结果
-
实现:
-
last-Modified和last-modified-since。
弊端:如何只是读文件,还是会造成last-Modified被修改,服务器不能命中导致重新发送资源,如果在1s内修改了文件,不会反应在last-modified上,导致不会重新发送文件
-
Eag 和 if-not-match
-
-
-
-
-
关于cookie和session机制
- cookie如果设置了过期时间,那么缓存在硬盘上,没有设置过期时间,缓存在内存上
- session拥有唯一的sessionid,通过cookie或者编码在url中传递给浏览器
- 区别:
- session存在服务器、cookie存在客服端
- cookie存储文件的大小有限制
- cookie只能保存文本,session可以保存任意类型的数据,结构是HashTable
-
localStorage和SessionStorage
- localStorage保存在本地,除非人为删除,否则不会删除
- SessionStorage存在于一次会话中,只要浏览器页面没有关闭,刷新页面或者同源的不同页面数据存在。
- 他们的大小一般只有5MB,只存文本类型不和客户端交互
-
事件冒泡和捕获
- 默认是冒泡,通过stopPropagation()停止
-
CORS
-
简单请求:不会引起CORS预检请求的请求
满足5个条件:
- get、post、head中的一个
- 人为定义的字段需要是fetch规范定义的对CORS安全的字段(Accept、Content-language、Accept-language)
- content-type:text/plain、multipart/form-data、application/x-www-form-urlencoding
- 请求中没有readableStream对象
-
Options预检请求
-
请求头:Access-Control-request-method、access-control-request-header、origin
响应头:Access-control-allow-method、access-control-allow-header、access-control-allow-origin
-
-
http
-
http1.0和http1.1的区别
- 缓存
- 24个错误状态码
- 有效利用带宽
- host头处理
- 长连接和请求流水线
-
SPDY
12年google发布了SPDY方案,优化了http1.x的延迟和安全性
- 采用多路复用技术。通过多个Steam共享一个tcp连接,解决线头阻塞问题,降低了延迟
- 设置优先级,优先级高的数据先传送
- header压缩
- https的安全传输
- 服务端推送
-
http2
-
基于SPDY的,但是也有不同,比如头部压缩算法,http2支持明文传输,SPDY默认https传输
-
和http1的不同:多路复用,采用二进制,header压缩,服务端推送
-
-
-
防抖和节流
function fd(fn, seconds){ let time; return function(){ if(time){ clearTimeout(time); } let self = this; let args = arguments; time = setTimeout(()=>{fn.apply(self, args)},seconds); } } function jl(fn, seconds){ let time; return function(){ if(time){ return; } let self = this; let args = arguments; time = setTimeout(()=>{ fn.apply(self, args)}, seconds); time = null; } } }
-
-
ES6有哪些语法?
- let
- 对象键值简写
- 模板字符串
- 箭头函数
- promise
- class
-
cookie
- name字段
- value字段
- domain字段
- Path字段
- SameSite字段 None、Strict、Lax
-
CSRF
- 攻击者引用用户访问一个网站,那个网站向被攻击网站发送攻击内容,由于用户登陆过被攻击的网站,所以这次跨域请求带有cookie,这样可以绕过用户的验证。
- 防护策略
- 针对不明外域访问
- 同源检测(Origin、Refer)
- samesite Cookie
- CSRF token(保存在session中)
- token输出到页面中
- 请求的时候携带这个token
- 针对不明外域访问
-
XSS攻击
-
HTML转义
-
设置白名单,禁止javescript:这种开头的链接
-
类型:存储型XSS攻击、反射型XSS攻击、DOM型XSS攻击
-
存储型和反射型的预防
- 纯前端渲染,把数据和代码分开,然后通过ajax加载用户数据,更新在页面上
- html转义
-
-
-
图片懒加载
function getLazyload(){ let imgs = document.getElementsByTagName('img'); let visualHight = window.innerHeight; let num = 0; return function(){ for(let i = num; i < imgs.length; ++i){ if(imgs[i].getBoundingClientRect().top < visualHight){ imgs[i].src = imgs[i].getAttribute('data-src'); ++num; } } } } let lazyload = getLazyload(); window.onload = lazyload; function debounce(fn, delay){ let time=null; return function(){ if(time){ clearTimeout(time); } let self = this; time = setTimeout(()=>{ fn.apply(self, arguments); }, delay); } } document.addEventListener('scroll', debounce(lazyload, 300), false);
-