web小结

DOM操作部分

DOM的数据结构是一种树

attribute和property的区别

节点的property

const pList document.querySelectorAll('p')
const p = pList[0]
console.log(p.style.width) //获取样式
p.style.width = '100px' //修改样式
console.log(p.className) //获取class
p.className = 'p1' //修改class

节点的attribute

const pList document.querySelectorAll('p')
const p = pList[0]
p.getAttribute('data-name')
p.setAttribute('data-name','p1')
p.getAttribute('style')
p.setAttribute('style','font-size:50px;')

区别

property:修改对象属性,不会体现到html结构中(推荐,不会重新渲染DOM)
attribute:修改html属性,会改变html结构。

DOM性能

1.DOM操作非常昂贵,应该避免频繁操作DOM

2.对DOM查询做缓存

3.将频繁操作改为一次性操作

//不缓存DOM查询结果
for(let i=0;i<document.getElementsByTagName('p').length;i++){}
//缓存DOM查询结果
const pList = document.getElementsByTagName('p')
const length =  pList.length
for(let i=0;i<length;i++){}

//将频繁操作改为一次性操作
const listNode = document.getrElementById('list')
//创建一个文档片段,此时还没有插入到DOM树中
const frag = document.createDocumentFragment()
//执行插入
for(let x = 0;x<10;x++){
  const li = document.createElement('li')
  li.innerHTML = 'list"+x
  frag.appendChild(li)
}
//都完成之后,再插入到DOM树中
listNode.appendChild(frag)

客户端存储

cookie localstorage 和sessionstorage

cookie

H5之前用来客户端存储数据
document.cookie = 'a:100'
缺点:1.存储大小,最大4KB.
2.http请求时需要发送到服务端,增加请求数据量
3.只能用document.cookie = ’‘来修改,太过简陋

localstorage 和sessionstorage

1.H5新增,专门为了存储而设计,最大可存5M
2.api简单易用:getItem,setItem
3.不会随着http请求发送出去。

区别

localstorage数据会永远存储,除非代码或者手动删除
sessionstorage数据只存储在当前会话,浏览器关闭则清空
一般用localstorage会更多一些

性能优化之防抖与节流

防抖debounce

监听一个input输入框的keyup,但是不能一松开键盘就触发事件,因为可能会频繁调用接口,应该松开若干毫秒后不再按下,才开始调用接口

const input1 = document.getElementById('input')
var timer = null
input1.addEventListener('keyup',function(){
  //假如输入123,首先输入1的时候,time是null,触发定时器,
  // 500毫秒之后打印,但是在500毫秒之内再次输入了2,触发keyup,此时time!=null
  // 就清空了原来应该打印1的定时器,重新执行一个新的定时器打印12,关键在于清空原来的定时器
  if(timer){   
    clearTimeout(timer)
  }
  timer = setTimeout(() => {
    console.log(input1.value)
    timer = null
  }, 500);
})
// 封装一个方法
function debounce(fn,delay = 500){
  // timer在闭包中
  let timer =null
  return function(){
    if(timer){   
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      fn()
      // fn.apply(this,arguments) 用这种更完美
      timer = null
    }, delay);
  }
}
input1.addEventListener('keyup',debounce(()=>{
  console.log(input1.value)
},1000))

节流throttle

拖拽一个元素时,要随时拿到该元素被拖拽的位置,直接用drag事件,则会频繁触发,很容易导致卡顿。 节流:无论拖拽速度多快,都会每隔100ms触发一次

const div1 = document.getElementById('div1')
var timer = null
div1.addEventListener('drag',function(e){
  //存在timer则说明前一次还没执行完,必须前一次执行完,才能执行下一次操作,确保规定时间只执行一次,
  // 和防抖的区别在于,防抖是清空原来执行新的,节流是执行原来的,正好相反
  if(timer){ 
    return
  }
  timer = setTimeout(() => {
    console.log(e.offsetX,e.offsetY)
    timer = null
  }, 500);
  
})

// 封装一个方法
function throttle(fn,delay = 500){
  // timer在闭包中
  let timer =null
  return function(){
    if(timer){   
      return
    }
    timer = setTimeout(() => {
      console.log(this) //this是div1,箭头函数承接上文,就是return的方法
      fn.apply(this,arguments) //只是为了绑定事件的参数,fn.apply({},arguments)也可以起到效果
      timer = null
    }, delay);
  }
}
div1.addEventListener('drag',throttle((e)=>{
  console.log(this) //this是window 箭头函数承接上文,就是window
  console.log(e.offsetX,e.offsetY)
},1000))
div1.addEventListener('drag',throttle(function(e){
  console.log(this) //this是div
  console.log(e.offsetX,e.offsetY)
},1000))

WEB安全

XSS跨站请求攻击

XSRF跨站请求伪造

1.XSS跨站请求攻击

<body>
  <div>123<div>
  <script>alert(document.cookie)</script>
</body>

往网页中恶意插入代码,获取用户信息,这样很轻松就获取到了用户的cookie信息,这是很不安全的。

预防

替换特殊字符,如< 变为< >变成>
<script>变为<script>直接显示,不会作为脚本执行
也可以用xss插件 Npm install xss

2.XSRF跨站请求伪造


微信截图_20201014173257.png
微信截图_20201014173325.png

微信截图_20201014173517.png

箭头函数

1.语法编写简洁,但是可读性不是很好。
2.没有自己的this,继承上级的this。
3.没有arguments
4.没有prototype,也就没有Constructor,也就是不能被new.

Flex布局

一、基本概念

采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称"项目"。


微信截图_20201015151059.png
微信截图_20201015151132.png
微信截图_20201015161833.png

1C:对象以数字123做健名时,会覆盖原来的字符串'123'的健名
2B:symbol是唯一属性
3C:以对象为属性时,会转为字符串'[object,object]',多个对象健名重复,取最后一个。

判断输入的是一个正确的URL

let str = 'https://www.sdafsdfdsf.cn/index.html?name=admin&age=22#video'
let reg = /(^(http|https|ftp):\/\/)?(([\w-]+\.)+[a-z0-9]+)((\/[^/?#]*)+)?(\?[^#]+)?(#.+)?$/i
console.log(reg.exec(str))
console.log(reg.test(str))

正向预查和负向预查

正向预查: ?= 表示一定要匹配, ?=[0-9] 必须匹配数字
负向预查: ?! 表示不能匹配, ?![0-9] 后面不能是数字

正则验证6-16位必须包含大写小写数字的字符串

let reg = /(?!^[a-zA-Z]+$)(?!^[0-9]+$)(?!^[a-z0-9]+$)(?!^[A-Z0-9]+$)(^[a-zA-Z0-9]{6,16}$)/

小括号代表一个组,一个小括号返回一个正则的结果true或者false.


微信截图_20201015172125.png
微信截图_20201016103821.png

答案:


微信截图_20201016104121.png

let obj = new Foo()时,调用了Foo(),当成普通函数执行,就改写了里面的Foo.a的指向,所以最后一个输出是1,new操作之后this就是obj,所以obj.a()输出2,私有属性有a(),就不去共有属性prototype上找了。

手写一个new 函数

function Dog(name){
  this.name = name
}
Dog.prototype.bark = function(){
  console.log('wangwang'+this.name)
}
function _new(fn, ...arg){
  // let obj ={}
  // obj.__proto__ = fn.prototype
  let obj = Object.create(fn.prototype) 
  // 上面两句等于Object.create(fn.prototype) 
  //Object.create(a对象) 等于创建一个空对象,并且让空对象作为a对象所属构造函数的实例,即obj.__proto__ =a对象
  fn.call(obj,...arg)
  return obj
}
var newDog = _new(Dog,'tom')
newDog.bark()

数据类型转换题

a=?的情况下
满足if(a==1&&a==2&&a==3){}

a= {
  n:0,
  toString:function(){
    ++this.n
  }
}

非常巧妙,因为当比较的两边数据类型不一样时,都是先转化为数字,对象转换为数字之前,先调用toString()方法转换成字符串,再转换为数字。所以重写它的toString()方法,覆盖原型链上的toString(),连续调用就可以实现以上效果。
再介绍两种方式:

//1
let a= [1,2,3]
a.toString = a.shift
//2
Object.defineProperty(window,'a',{
  get:function(){
    this.value?this.value++:this.value = 1
    return this.value
  }
})

各位应该能看懂。

再出一题

微信截图_20201016164545.png

接下来三大经典算法

冒泡排序

 // 冒泡排序:当前项和后一项比较,如果当前项比后一项大,则让大的靠后
let arr =[12,8,24,16,1,88,66,34,67,99,1]
 function getArr(arr){
  let count = arr.length
  for(let i = 0;i<count-1;i++){
    for(let j = 0;j<count-i-1;j++){
      if(arr[j]>arr[j+1]){
        [arr[j],arr[j+1]] = [arr[j+1],arr[j]]
      }
    }
  }
  return arr
 }
 getArr(arr)

插入排序

//插入排序:打扑克牌,抓一张牌,插到手里,进行排序的过程。
function insert(arr){
  let count = arr.length
  let newArr = [arr[0]] // 存储第一张牌
  for(let i = 1;i<count;i++){ //依次抓牌 i从1开始,因为0已经存进去了
    let A = arr[i] //新抓的牌
     for(let j= newArr.length-1;j>=0;j--){
       let B = newArr[j] //每一次比较手里的牌
       if(A>B){
        newArr.push(A)
        // newArr.splice(j+1,0,A) //如果当前新牌比手里要比较的牌大,就插在后面
        break
       }
       if(j===0){
        newArr.unshift(A) //比到第一张了,就插在第一张
       }
     }
  }
  console.log(newArr)
  return newArr
}
insert(arr)

快速排序

let arr =[12,8,24,16,1,88,66,34,67,99,1]
 //快速排序,找到中间项,把他从原来的数组中移除,获取这一项的结果
 function quick(arg){
   //4.结束递归(ary种小于等于一项)
  if(arg.length<=1){
    return arg
  }
  //1.找到数组的中间项,在原有数据中删除
  let middleIndex =  Math.floor(arg.length/2)
  let middleValue =  arg.splice(middleIndex,1)[0]
  //2.准备左右两个数组,循环剩下数组中的每一项,小的放左大的方右
  let arrleft=[],arrRight = [];
  for(let i=0;i<arg.length;i++){
    if(arg[i]<middleValue){
      arrleft.push(arg[i])
    } else {
      arrRight.push(arg[i])
    }
  }
  //3 递归操作
  return quick(arrleft).concat(middleValue,quick(arrRight))

 }
 let a = quick(arr)
 console.log(a)

计算斐波那契

1。普通递归:代码优美逻辑清晰。但是有重复计算的问题,如:当n为5的时候要计算fibonacci(4) + fibonacci(3),当n为4的要计算fibonacci(3) + fibonacci(2) ,这时fibonacci(3)就是重复计算了。运行 fibonacci(50) 会出现浏览器假死现象,毕竟递归需要堆栈,数字过大内存不够。

function fibonacci(n) {
    if (n == 1 || n == 2) {
        return 1
    };
    return fibonacci(n - 2) + fibonacci(n - 1);
}
fibonacci(30)

2.方法二:改进递归-把前两位数字做成参数避免重复计算

function fibonacci(n) {
    function fib(n, v1, v2) {
        if (n == 1)
            return v1;
        if (n == 2)
            return v2;
        else
            return fib(n - 1, v2, v1 + v2)
    }
    return fib(n, 1, 1)
}
fibonacci(30)

3.普通for循环

function fibonacci(n) {
    var n1 = 1, n2 = 1, sum;
    for (let i = 2; i < n; i++) {
        sum = n1 + n2
        n1 = n2
        n2 = sum
    }
    return sum
}
fibonacci(30)

4.for循环+解构赋值

var fibonacci = function (n) {
    let n1 = 1; n2 = 1;
    for (let i = 2; i < n; i++) {
        [n1, n2] = [n2, n1 + n2]
    }
    return n2
}
fibonacci(30)

正向代理和反向代理

QQ截图20201023162443.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容