前端总结

前端优化

  • 减少http请求, 合理设置http缓存

    • 合并css 合并js 合并图片

  • 使用浏览器缓存

    • 设置http头的Cache-Control 和 Expires设置缓存有效期

  • 对代码使用gzip压缩

  • css sprite svg font

  • 图片懒加载

  • css放在最上面,JavaScript放在后面,浏览器碰到js立即执行,阻断了后面的进程

  • 减少cookie的传输

  • 在页面加载完后触发方法 window.onload

  • js优化

    • 避免eval 和function

    • 减少作用域查找

    • css选择符优化,层级不宜过多

    • cdn加速,cdn本质缓存,数据缓存在离用户最近的地方,使用户最快的获取到数据,一般多是静态资源文件

    • Nginx反向代理,分发用户请求

防抖与节流

// 使用setTimeout来存放待执行的函数, 然后使用clearTimeout在合适的时机清除待执行的函数

// 防抖 不管事件发生的频率多快,一定在wait的时间后执行,记录开始的timer延时事件, 新事件有操作,后面覆盖前面的事件,最后那一次一定触发
function debounce (fn, wait) {
    let timer = null
  return function (...args) {
    clearTimeout(timer)
    timer = setTimeout(() => {
      fn.apply(this, args)
    }, wait)
    }
}

// 节流 不管事件发生频率多快,在wait时间内,无论怎么去触发,执行效果只有一次。 timer存在就不会执行下面的操作。只有在执行下面的操作重置timer为null,事件在wait时间内执行完毕后才能触发下次事件
function throttle (fn, wait) {
  let timer = null
  return function (...args) {
    if (!timer) {
      timer = setTimeout(() => {
        fn.apply(this, args)
        timer = null
      }, wait)
    }
    }
}

 

严格判断数据类型

Object.prototype.toString.call({}) => [Object Object]
Object.prototype.toString.call([]) => [Object Array]
typeof() 判断简单类型 undefined => undefined null => Object array => object 

 

实现promise

function Promis (exactor) {
  let _this = this
  _this.status = 'padding'
  _this.failCallBack = null
  _this.successCallBack = null
  exactor(resolve.bind(_this), reject.bind(_this))
  function resolve (params) {
    if (_this.status == 'padding') {
      _this.status = 'success'
      _this.successCallBack(params)
    }
  }
  function reject (params) {
    if (_this.status == 'padding') {
      _this.status = 'fail'
      _this.failCallBack(params)
    }
  }
}
Promis.prototype.then = function (full, fail) {
  this.successCallBack = full
  this.failCallBack = fail
}

new Promis((resolve, reject) => {
    setTimeout(() => {
    resolve('成功')
  }, 1000)
}).then(res => {
  console.log(res)
})

vue的生命周期

beforeCreate: 实例创建之前,不能访问到实例的data和method
created: 实例创建完成 这时候能够访问实例的data和method
beforeMounted: 实例挂在到dom树之前
mounted: 实例dom挂载完成,可以操作dom
beforeUpdate: 数据更新之前
update: 数据更新完成
beforeDestoryed: 实例销毁之前
destoryed: 实例销毁 

闭包

// 定义:能狗访问局部作用域的函数,上级函数作用域不会被清除
// 应用 自执行函数
for (var i = 0; i < 5; i++) {
    (function son(j) {
    setTimeout(() => {
      console.log(j)
    }, j * 1000)
    })(i)
}
// 每隔1s输出 0 1 2 3 4

for (var i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i)
  }, i * 1000)
}
// 每隔1s输出 5 5 5 5 5

原型链和原型

// 实例被构造函数通过new关键字构建出来,实例的__proto__会指向构造函数的prototype, 构造函数的prototype的__proto__指向Function.prototype, Function.prototype的__proto__会指向Object.prototype, 而Object.prototype的__proto__会指向null,这样就形成了一条原型链。实例可以通过原型链寻找自己本身没有的方法,有利于方法的拓展。如Object.prototype.toString.call({}) 

js继承

  • 原型链继承: 通过原型链指向继承,引用属性会共用,不能向父级传递参数

  • 构造函数继承:通过call或apply改变this指向调用父函数,属性不会共享, 可以向父级传递参数,复用性不强

  • 组合继承:通过call或apply改变this指向调用父函数,属性不会共享,可以向父级函数传递参数,能够实现代码的复用

  • 原型式继承: 借助原型已有对象创建新对象,需要一个对象作为父级基础, 父级引用属性可以共用

  • 寄生式继承: 借助原型已有对象创建新对象,并给他添加方法或属性,并且返回这个对象,父级阴影属性不能共用

  • 寄生组合式继承: 通过call或apply改变this指向调用父函数,然后将父函数的原型复制给子函数,并且改变子函数的额原型的constructor,引用属性不会共用, 能够向父函数传递参数,有好的复用性

  • es6继承 extend

class father {
  constructor ({name, age}) {
    this.name = name
    this.age = age
  }
  sayHi () {
    console.log('哈哈哈')
  }
}
class Son extends father {
    constructor (arr) {
    super(arr)
  }
  sayName () {
    console.log(this.name)
  }
}
const peo = new Son({
  name: '张三',
  age: 13
})
peo.sayHi() // 哈哈哈
peo.sayName() // 张三
console.log(peo) // { name: '张三', age: 13, __proto__: father }

 call和apply、bind的区别

// call和apply、bind都是改变函数内部的指向
// call和apply是直接调用, 传入参数call可以接受多个参数, apply是接受一个数组
// bind是返回一个函数,需要再次调用
Function.prototype.myCall = function (context) {
  // 赋值作用域,没有就默认window,即访问全局
  context = context || window
  context.fn = this
  let args = [...arguments].slice(1)
  // 4.执行调用函数就是第二步保存的fn,记录返回值
  let result = context.fn(...args);
  // 5.销毁调用函数,以免作用域污染;
  Reflect.deleteProperty(context, 'fn');
  return result;
}


 Function.prototype.mApply = function(context) {
    context = context || window;
    context.fn = this;
    let result;
    if (arguments[1]) {
        result = context.fn(...arguments[1]);
    } else {
        result = context.fn();
    }
    Reflect.deleteProperty(context, "fn");
    return result;
}

test.mApply(tempObj, [1, 2, 3]);

Function.prototype.mBind = function (context) {
  // 获取绑定时的传参
  let args = [...arguments].slice(1),
  // 定义中转构造函数,用于通过原型连接绑定后的函数和调用bind的函数
  F = function () {},
  // 记录调用函数,生成闭包,用于返回函数被调用时执行
  self = this,
  // 定义返回(绑定)函数
  bound = function () {
    // 合并参数,绑定时和调用时分别传入的
    let finalArgs = [...args, ...arguments]

    // 改变作用域,注:aplly/call是立即执行函数,即绑定会直接调用
    // 这里之所以要使用instanceof做判断,是要区分是不是new xxx()调用的bind方法
    return self.call((this instanceof F ? this : context), ...finalArgs)
  }

  // 将调用函数的原型赋值到中转函数的原型上
  F.prototype = self.prototype
  // 通过原型的方式继承调用函数的原型
  bound.prototype = new F()
  return bound
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值