博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
前端面试之JS
阅读量:6388 次
发布时间:2019-06-23

本文共 11961 字,大约阅读时间需要 39 分钟。

es5原型继承的例子

// 组合继承function Father(value){ this.val = value}Father.prototype.getVal = function(){    return this.val}function Son(value){    Father.apply(this,arguments)}Son.prototype = new Father() var son = new Son(1234)console.log(son)// 寄生组合继承function Father(value){    this.val = value}Father.prototype.getVal = function(){    console.log(this.val)}function Son(){    Father.apply(this,arguments)}Son.prototype = Object.create(Father.prototype)Son.prototype.constructor = Son// Son.prototype = Object.create(Parent.prototype,{
// constructor:{
// value:Son,// enumerable:false,// writeable:true,// configurable:true// }// })//es6的写法 class Person { constructor(value) { this.val = value } get() { console.log(this.val) } } class son extends Person { constructor(value,name) { super(value) this.name = name } }复制代码

手写promise

const PENDING = 'pedeing'    const RESOLVED = 'resolved'    const REJECTED = 'rejected'    function myPromise(fn) {        const that = this        that.state = PENDING        that.value = null        that.reslovedCallbacks = []        that.rejectedCallbacks = []        function resolve(value) {            if (that.state === PENDING) {                that.state = RESOLVED                that.value = value                //  完整then里面的第一个回调                that.reslovedCallbacks.map(thenResolve => thenResolve(that.value))            }        }        function reject(value) {            if (that.state === PENDING) {                that.state = REJECTED                that.value = value                // 完整then里面的第一个回调                that.rejectedCallbacks.map(thenReject => thenReject(that.value))            }        }        fn(resolve, reject)    }    myPromise.prototype.then = function(onFullfilled, onRejected){        const that = this        onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : v => v        onRejected = typeof onRejected === 'function' ? onRejected : r => { throw r }        if(that.state === PENDING){            that.reslovedCallbacks.push(onFullfilled)            that.rejectedCallbacks.push(onRejected)        }        if(that.state === RESOLVED){            onFullfilled(that.value)        }        if(that.state === REJECTED){            onRejected(that.value)        }    }复制代码

原生XHR

var xhr = new XMLHttpRequest()    xhr.open('GET','api',false)    xhr.onreadystatechange = function(){      if(xhr.readyState === 4){          if(xhr.status === 200){          }      }    }    xhr.send(null)复制代码

原生实现事件代理

function bindEvent(elem, type, selecter, fn) {    if (!fn) {      fn = selecter      selecter = null    }    elem.addEventListener(type, (e) => {      var target      if (selecter) {        target = e.target        if (target.matches(selecter)) {          fn.call(target, e)        }      } else {        fn(e)      }    })  }复制代码

节流和防抖

1、防抖就是控制函数在高频触发的状态下,在最后一次事件触发后延迟一定时间执行

var debounce = function(time , func){    let lastTimer = 0    return function(...args){        clearTimeout(lastTimer)        lastTimer = setTimeout(()=>{            func.apply(this,args)        },time)    }}复制代码

2、节流就是在高频请求中,将请求控制在时间范围之外,以减少请求次数

var throttle = function(func, time){    let  lastTime = 0    return function(...args){        let  now = +new Date()        if(now-lastTime > time){            lastTime = now            func.apply(this,args)        }    }}复制代码

手动实现前端路由

function Router(){  this.currentUrl='';  this.routes={};}Router.prototype.route = function(path,callback){  this.routes[path] = callback || function(){}}Router.prototype.refresh = function(){  this.currentUrl = location.hash.slice(1) || '/';  this.routes[this.currentUrl]();}Router.prototype.init = function(){  window.addEventListener('load',this.refresh.bind(this),false);  window.addEventListener('hashchange',this.refresh.bind(this),false);  // console.log(location.hash)  // if(location.hash.slice(1)!=='/')  //     location.hash = '#/';} // hash  hashChage// history  pushState replaceState复制代码

vue实现数据响应式的原理

vue在2.0时代使用object.definedProperty()实现数据的响应,通过此函数监听get() 和 set() 事件,3.0时代将采用proxy实现,一下是代码

function observe(obj){    // 边界    if(!obj || typeof obj !== 'object')    return        Object.keys(obj).forEach(key => {        definedReacted(obj,key,obj[key])    })}function definedReacted(obj,key,value){    observe(value)    Object.definedProperty(obj,key,{        // 可枚举        enumerabeke:true,        //可配置        configurable:true,        get:()=>{            console.log(value)            return value        },        set:(newValue)=>{            console.log(newValue)            val = newValue        }    })}function observer(obj){    // 递归边界    if(!obj || typeof obj !== 'object'){        return    }    Object.keys(obj).forEach((item,index,arr)=>{        defineReactive(obj,item,obj[item])        observer(obj[item])    })}function defineReactive(data,key,val){    Object.defineProperty(data,key ,{        enumerable:true,        configurale:true,        get:function(){            // 需要在这里添加订阅者            return val        },        set:function(newValue){            val = newValue            console.log('属性'+key+'被监听了'+'现在的值为'+newValue)            // 在这里通知订阅者去更新视图        }    })}var library = {    book1: {        name: ''    },    book2: ''};observer(library)library.book1.name = 'vue权威指南'; // 属性name已经被监听了,现在值为:“vue权威指南”library.book2 = '没有此书籍';复制代码

两个数不使用四则运算得出和

function sum(a, b) {    if (a == 0) return b    if (b == 0) return a    let newA = a ^ b   // 获得个数值    let newB = (a & b) << 1 // 获得进位的数值    return sum(newA, newB)  // 最后执行自己 }复制代码

冒泡排序

function isArray(array) {        if (Object.prototype.toString.call(array) !== '[object Array]') {            return array        }    }    function swap(array, left,right) {        var temp = array[left]        array[left] = array[right]        array[right] = temp    }    function bubble(arr) {        isArray(arr)        for (let i = arr.length - 1; i > 0; i--) {            for (let j = 0; j < i; j++) {                if (arr[j] > arr[j + 1]) swap(arr,j,j+1)            }        }        return arr    }复制代码

插入排序

function insert(array){    isArray(array)    for(let i = 0 ;i
=0&&array[j]>array[j+1];j--){ swap(array,j,j+1) } } return array}复制代码

选择排序

const choose = (arr) => {    isArray(arr)    for (let i = 0; i < arr.length - 1; i++) {       let minIndex = i        for (let j = i + 1; j < arr.length; j++) {            minIndex = arr[j] < arr[minIndex] ? j : minIndex        }        if (i !== minIndex) {            swap(arr, i, minIndex)        }    }    return arr}复制代码

快速排序

// 阮一峰版本function quicksort(arr){    isArray(arr)    if(arr.length<=1) return arr    // const pivotIndex = Math.floor(Math.random()*arr.length)    const pivotIndex = Math.floor(arr.length/2)    const pivot = arr.splice(pivotIndex,1)[0]    console.log(pivot,arr)    const left = []    const right = []    for(let i = 0; i
pivot){ right.push(arr[i]) }else{ left.push(arr[i]) } } return quicksort(left).concat([pivot],quicksort(right))}console.log(quicksort([2,4,1,88,2,5,90,564,32]))复制代码

手写call apply bind

let a = {    name: 'leolei',    fn: function (a, b) {        console.log(this.name + a + b)    }}const b = {    name: 'cuisiyao'}Function.prototype.test = function (){    // 查看在prototype上添加方法 在调用时this是什么    console.log(this === a.fun.__proto__)}Function.prototype.Mycall = function () {    if (typeof this === 'Function') {        throw new TypeError('Error')    }    // 处理没有参数的默认情况    const context = arguments[0] || window    console.log(this)    context.fn = this    const args = [...arguments].slice(1)    console.log(args)    const results = context.fn(...args)    delete context.fn    return results}Function.prototype.Myapply = function () {    if (typeof this === 'Function') {        throw new TypeError('Error')    }    const context = arguments[0] || window    console.log(this)    context.fn = this    const args = arguments[1]    console.log(args)    const results = context.fn(...args)    delete context.fn    return results}Function.prototype.Mybind = function () {    const context = arguments[0] || window    const args1 = [...arguments].slice(1)    const _this = this    return function F(...args) {        // 处理new function 的情况        if (this instanceof F) {            return new _this(...args, ...args1)        }        return _this.Myapply(context, args.concat(args1))    }}a.fn.Mycall(b, 123, 456)a.fn.Myapply(b, [123, 456])// 当方法执行a.fn.Mybind(b, 123, 456)()a.fn.Mybind(b)(123, 456)a = {    name: 'leolei',    fn: function (a, b) {        console.log(a + b)    }}// 使用new执行new a.fn(123, 456)const test = new (a.fn.Mybind(b))(123, 456)复制代码

讲述一个new的过程

  • 先创建一个空的obj
  • 然后将需要构造的函数的绑定到空对象的obj原型原型上
  • 在新建空对象的环境下执行构造函数,绑定this为这个空对象
  • 返回this,并确保this为Object
function creat(){    const obj = {}    const con = [].shift.call(arguments)    obj.__proto__ = con    const results = con.aplly(obj,arguments)    return results instanceof Object ? results : obj}复制代码

常见的浏览器安全漏洞

  • XSS攻击,分为两种。
    • 一种是持久行的,持久型的XSS攻击主要是通过可执行的网页代码,将数据写到后台数据库中,比如评论时写入<script>aler(1)</script>,将此评论注入到数据库中,如果不做处理,页面在访问时会受到攻击。
    • 第二种非持久型的,主要通过导航栏工具http://www.domain.com?name=<script>alert(1)</script>. 解决方案:1. 一般采用转义字符来解决,比如转义<&lt
  • CSRP 跨站伪造请求。
    • 当用户登录A页面时,已登录网站,未关闭,此时存在了cookie。用户在此时打开了另外一个攻击网站B,B盗取A的cookie后对A页面的后台进行请求,并攻击。
    • 解决方案:在http头中设置SameSite,让cookie不随跨域请求发送。验证refrer字段 判断 请求来源,禁止第三方请求发送。使用token通过服务器验证用户登录是否有效。
  • 点击劫持。解决方案,在响应头设置X—FRSME—OPTIONS。
  • 中间人攻击 容易出现在公用产所的 wifi,解决方案就是使用https协议。

vue路由守卫

全局守卫

  • beforeEnter(to,from,next)
  • afterEnter(....)
  • beforeResolve

路由独享守卫

  • beforeEnter

组件内的守卫

  • beforeRouteEnter
  • beforeRouteUpdata
  • beforeRouteLeave

完整的解析过程

  • 导航被触发
  • 上一个导航的组件里调用beaforeRouteLeave
  • 激活全局beforeEnter
  • 如果是重用组件,那就会调用beforeRouteUpdata
  • 然后进入路由配置的beforEnter
  • 解析异步路由组件
  • 调用全局的beforeResolve
  • 导航被确认
  • 调用全局的afterEnter
  • 触发更新dom
  • 用创建好的实例调用beforeRouteEnter,并把组件实例作为使用next的回调

设计模式

  • 工厂模式 隐藏对象创建的过程
  • 单例模式 js可以借助闭包的方式完成
  • 适配器模式 在不对原有接口做任何改动的情况下,包装一层新的接口,返回最终数据
  • 代理模式 proxy 在vue3.0中正在使用这个特性实现数据的双向绑定,现在是使用Object.definedProperty实现的,
  • 观察者模式
  • 发布-订阅者模式,这两种模式看似相同其实不同 观察者模式是观察者直接通知对象,双方知道对方的存在,发布-订阅者模式,双方不知道对方存在,使用中间对象对发布的信息进行删选然后通知订阅者。
  • 装饰模式 在不改变以后接口,对方法进行包装。
  • 外观模式,比如说写一个原生函数创建个浏览器环境下的XHR对象

vue生命周期

  • beforeCreate
  • created
  • beforeMount
  • mounted
  • beforeupdate
  • updated
  • beforeDestroy
  • disrtoryed

对于使用keep-alive的组件 有独有的deactived和actived 生命周期,在切换组件时此组件不会被销毁,而是缓存到内存并执行deactived ,命中缓存之后会调用actived

js中的原始类型

  • boolean
  • null
  • undfined
  • Number
  • String
  • Symbol

typeof有几种结果

  • undefined
  • boolean
  • Object
  • Number
  • String
  • Function

JS中有哪些内置函数

上面的这几种加上 Array Regexp Date Error

移动端首屏优化

  • 采用服务器渲染ssr
  • 按需加载配合webpack分块打包
  • 很有必要将script标签➕异步
  • 有轮播图 最好给个默认 另外要处理图片懒加载
  • 打包线上也要注意去掉map 文件
  • 组件懒加载
  • 路由懒加载
  • webpack的一切配置 肯定是必须的 这个百度去 做到js css 以及依赖库分离
  • 强烈建议不要在应用依赖里面去下载jQuery库和一些Ui库
  • 压缩图片 https://tinypng.com/
  • 建议还是用webpack的图片压缩插件
  • 使用pagespeed看看有哪些可优化的选项

最优二叉树

class Node {    constructor(value) {        this.value = value        this.left = null        this.right = null    }}class BST {    constructor() {        this.root = null        this.size = 0    }    getSize() {        return this.size    }    isEmpty() {        return this.size === 0    }    addNode(value) {        this.root = this._addchild(this.root, value)    }    _addchild(node, value) {        if (!node) {            this.size++            return new Node(value)        }        if (node.value > value) {            node.left = this._addchild(node.left, value)        } else{            node.right = this._addchild(node.right, value)        }        return node    }}复制代码

class Stack{    constructor(){        this.stack = []    }    push(val){        this.stack.unshift(val)    }    pop(){        this.stack.shift()    }    peek(){        return this.stack[this.getCount()-1]    }    getCount(){        return this.stack.length    }}// 这里其实可以使用数组直接模拟栈 队列其实也是一样的// 检测下列字符串是否是回文字符串var str = 'leel'function isValied(str){    var strArr = str.split('')    var stack = []    for(let i =0;i

转载地址:http://epcha.baihongyu.com/

你可能感兴趣的文章
Linux 计划任务
查看>>
flask的orm操作
查看>>
如何防止驱动被恶意利用
查看>>
Nagios的搭建
查看>>
我的友情链接
查看>>
Oracle SQL之--多表查询基础用法
查看>>
图形化插件对Eclipse的版本要求
查看>>
两个关于数列的Python脚本(斐波那契数列和猴子吃香蕉类问题)
查看>>
olabuy-时光从来素默,内心应保持一份素淡与简静
查看>>
kux文件怎么打开 苹果手机如何观看kux视频
查看>>
Python中的urllib.request模块
查看>>
第九课 《说人话》
查看>>
js对象数组排序
查看>>
如何实现在展示商品时,放大商品细节
查看>>
uboot boot流程分析
查看>>
如何学习PHP整个体系的?
查看>>
css三角形实现写法全攻略收集
查看>>
Enterprise and the press public MBT Fora
查看>>
js常用代码整理
查看>>
富文本编辑器TinyMCE
查看>>