.container {
display: grid;
grid-template-columns: 100px auto 200px;
}
复制代码
Function.prototype.myBind = function(content) {
if(typeof this !='function'){
throw Error('not a function')
}
let _this = this;
let args = [...arguments].slice(1)
let resFn=function(){
return _this.apply(this instanceof resFn?this:content,args.concat(...arguments))
}
return resFn
};
/** * 每一个函数均可以调用call方法,来改变当前这个函数执行的this关键字,而且支持传入参数 */
Function.prototype.myCall=function(context=window){
context.fn = this;//此处this是指调用myCall的function
let args=[...arguments].slice(1);
let result=content.fn(...args)
//将this指向销毁
delete context.fn;
return result;
}
/** * apply函数传入的是this指向和参数数组 */
Function.prototype.myApply = function(context=window) {
context.fn = this;
let result;
if(arguments[1]){
result=context.fn(...arguments[1])
}else{
result=context.fn()
}
//将this指向销毁
delete context.fn;
return result;
}
复制代码
[...new Set(arr)]
复制代码
var arr = [1,2,1,2,3,5,4,5,3,4,4,4,4],
init=[]
var result = arr.sort().reduce((init, current)=>{
console.log(init,current)
if(init.length===0 || init[init.length-1]!==current){
init.push(current);
}
return init;
}, []);
console.log(result);//1,2,3,4,5
复制代码
var deBounce=function(fn,wait=300){
let timer
return function(){
if(timer){
clearTimeOut(timer)
}
timer=setTimeOut(()=>{
fn.apply(this,arguments)
},wait)
}
}
var throttle = function (fn, wait = 300) {
let prev = +new Date();
return function () {
const args = argument,
now = +new Date();
if (now > prev + wait) {
prev = now;
fn.apply(this, args)
}
}
}
复制代码
//0 pending,1 resolve,2 reject
function Promise(fn) {...
this._state = 0 // 状态标记
doResolve(fn, this)
}
function doResolve(fn, self) {
var done = false // 保证只执行一个监听
try {
fn(function(value) {
if (done) return
done = true
resolve(self, value)
}, function(reason) {
if (done) return;
done = true
reject(self, value)
})
} catch (err) {
if (done) return
done = true
reject(self, err)
}
}
function resolve(self, newValue) {
try {
self._state = 1;
...
} catch (err) {
reject(self, err)
}
}
function reject(self, newValue) {
self._state = 2;
...
if (!self._handled) {
Promise._unhandledRejectionFn(self._value);
}
}
复制代码
funtion deepCopy(obj){
let result;
if(typeofObj=='object'){
//复杂数据类型
result=obj.constructor==Array?[]:{}
for (let i in obj){
result[i]=typeof obj[i]=='object'?deepCopy(obj[i]):obj[i]
}
}else{
//简单数据类型
result=obj
}
return result
}
复制代码
function commafy(num) {
return num && num
.toString()
.replace(/(\d)(?=(\d{3})+\.)/g, function($0, $1) {
return $1 + ",";
});
}
console.log(commafy(1312567.903000))
复制代码
javascript是单线程语言,任务设计成了两类,同步任务和异步任务 同步和异步任务分别进入不一样的执行“场所”,同步进入主线程,异步进入Event Table并注册函数。当指定的事情完成时,Event Table会将这个函数移入Event Queue。主线程内的任务执行完毕为空,回去了Event Queue读取对应的函数,进入主线程。 上述过程会不断重复,也就是常说的Event Loop(事件循环)。 可是,JS异步还有一个机制,就是遇到宏任务,先执行宏任务,将宏任务放入event queue,而后再执行微任务,将微任务放入eventqueue,可是,这两个queue不是一个queue。当你往外拿的时候先从微任务里拿这个回调函数,而后再从宏任务的queue拿宏任务的回调函数 宏任务通常包括:总体代码script,setTimeout,setInterval。 微任务:Promise,process.nextTickjavascript
事件冒泡和事件捕获php
事件流分为:冒泡和捕获,顺序是先捕获再冒泡。css
事件冒泡:子元素的触发事件会一直向父节点传递,一直到根结点中止。此过程当中,能够在每一个节点捕捉到相关事件。能够经过stopPropagation方法终止冒泡。html
事件捕获:和“事件冒泡”相反,从根节点开始执行,一直向子节点传递,直到目标节点。前端
事件捕获阶段 addEventListener给出了第三个参数同时支持冒泡与捕获:默认是false,事件冒泡;设置为true时,是事件捕获。vue
事件委托 事件委托是指将事件绑定目标元素的到父元素上,利用冒泡机制触发该事件java
event.target返回触发事件的元素react
event.currentTarget返回绑定事件的元素面试
//方法1
function create(){
//1.建立一个空对象
let obj={}
//2.获取构造函数
let Con=[].shift.call(arguments)
//3.设置空对象的原型
obj._proto_=Con.prototype
//4.绑定this并执行构造函数,给新对象添加属性和方法
let result=Con.apply(obj,arguments)
//5.确保返回值为对象
return result instanceof Object?result:obj
}
//方法2
//经过分析原生的new方法能够看出,在new一个函数的时候,
// 会返回一个func同时在这个func里面会返回一个对象Object,
// 这个对象包含父类func的属性以及隐藏的__proto__
function New(f) {
//返回一个func
return function () {
var o = {"__proto__": f.prototype};
f.apply(o, arguments);//继承父类的属性
return o; //返回一个Object
}
}
复制代码
/* 封装ajax函数 * @param {string}opt.type http链接的方式,包括POST和GET两种方式 * @param {string}opt.url 发送请求的url * @param {boolean}opt.async 是否为异步请求,true为异步的,false为同步的 * @param {object}opt.data 发送的参数,格式为对象类型 * @param {function}opt.success ajax发送并接收成功调用的回调函数 */
function myAjax(opt){
opt = opt || {};
opt.method = opt.method.toUpperCase() || 'POST';
opt.url = opt.url || '';
opt.async = opt.async || true;
opt.data = opt.data || null;
opt.success = opt.success || function () {}
let xmlHttp = null;
if (XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}else{
xmlHttp =new ActiveXObject('Microsoft.XMLHTTP')
}
let params;
for (var key in opt.data){
params.push(key + '=' + opt.data[key]);
}
let postData = params.join('&');
if (opt.method.toUpperCase() === 'POST') {
xmlHttp.open(opt.method, opt.url, opt.async);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');
xmlHttp.send(postData);
}else if (opt.method.toUpperCase() === 'GET') {
xmlHttp.open(opt.method, opt.url + '?' + postData, opt.async);
xmlHttp.send(null);
}
xmlHttp.onreadystatechange= function () {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
opt.success(xmlHttp.responseText);//若是是json数据能够在这使用opt.success(JSON.parse( xmlHttp.responseText))
}
};
}
复制代码
var url = "http://www.taobao.com/index.php?key0=0&key1=1&key2=2";
function parseQueryString(url){
var str = url.split("?")[1], //经过?获得一个数组,取?后面的参数
items = str.split("&"); //分割成数组
var arr,name,value;
for(var i=0; i<items.length; i++){
arr = items[i].split("="); //["key0", "0"]
name = arr[0];
value = arr[1];
this[name] = value;
}
}
var obj = new parseQueryString(url);
alert(obj.key2)
复制代码
HTTP协议(超文本传输协议)ajax
1.1 改进:
HTTP之请求消息Request
HTTP之响应消息Response
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
SYN (同步序列编号)ACK(确认字符)
这是由于服务端在LISTEN状态下,收到创建链接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭链接时,当收到对方的FIN报文时,仅仅表示对方再也不发送数据了可是还能接收数据,己方也未必所有数据都发送给对方了,因此己方能够当即close,也能够发送一些数据给对方后,再发送FIN报文给对方来表示赞成如今关闭链接,所以,己方ACK和FIN通常都会分开发送。
非对称加密与对称加密双剑合璧,使用非对称加密算法传递用于对称加密算法的密钥,而后使用对称加密算法进行信息传递。这样既安全又高效
当浏览器再次访问一个已经访问过的资源时,它会这样作:
其实 VNode 是对真实 DOM 的一种抽象描述,它的核心定义无非就几个关键属性,标签名、数据、子节点、键值等,其它属性都是都是用来扩展 VNode 的灵活性以及实现一些特殊 feature 的。因为 VNode 只是用来映射到真实 DOM 的渲染,不须要包含操做 DOM 的方法,所以它是很是轻量和简单的。 Virtual DOM 除了它的数据结构的定义,映射到真实的 DOM 实际上要经历 VNode 的 create(用JS对象模拟DOM树)、diff(比较两棵虚拟DOM树的差别)、patch(把差别应用到真正的DOM树上) 等过程。
对树进行分层比较,两棵树只会对同一层次的节点进行比较。(由于 DOM 节点跨层级的移动操做少到能够忽略不计) 若是父节点已经不存在,则该节点及其子节点会被彻底删除掉,不会用于进一步的比较。 注意: React 官方建议不要进行 DOM 节点跨层级的操做,很是影响 React 性能。 在开发组件时,保持稳定的 DOM 结构会有助于性能的提高。例如,能够经过 CSS 隐藏或显示节点,而不是真的移除或添加 DOM 节点。
若是是同一类型的组件,按照原策略继续比较 virtual DOM tree(tree diff)。 对于同一类型的组件,有可能其 Virtual DOM 没有任何变化,若是可以确切的知道这点那能够节省大量的 diff 运算时间,所以 React 容许用户经过 shouldComponentUpdate() 来判断该组件是否须要进行 diff。 若是不是,直接替换整个组件下的全部子节点。
对处于同一层级的节点进行对比。 这时 React 建议:添加惟一 key 进行区分。虽然只是小小的改动,性能上却发生了翻天覆地的变化! 如: A B C D --> B A D C 添加 key 以前: 发现 B != A,则建立并插入 B 至新集合,删除老集合 A;以此类推,建立并插入 A、D 和 C,删除 B、C 和 D。 添加 key 以后: B、D 不作任何操做,A、C 进行移动操做,便可。 建议:在开发过程当中,尽可能减小相似将最后一个节点移动到列表首部的操做,当节点数量过大或更新操做过于频繁时,在必定程度上会影响 React 的渲染性能。
Object.defineProperty(obj, prop, descriptor)
observe
// 解析模板字符串生成 AST
const ast = parse(template.trim(), options)
//优化语法树
optimize(ast, options)
//生成代码
const code = generate(ast, options)
复制代码
vuex
预防:
使用XSS Filter
<script>
中,能够进行JS编码。使用 HttpOnly Cookie 将重要的cookie标记为httponly,这样的话当浏览器向Web服务器发起请求的时就会带上cookie字段,可是在js脚本中却不能访问这个cookie,这样就避免了XSS攻击利用JavaScript的document.cookie获取cookie。
CSRF:跨站请求伪造,也称 XSRF,是一种挟制用户在当前已登陆的Web应用程序上执行非本意的操做的攻击方法。与 XSS 相比,XSS利用的是用户对指定网站的信任,CSRF利用的是网站对用户网页浏览器的信任。