前端知识摘录

1. vue、react异同点

比较:
1、vue使用的则是html一个简答的扩展,基础语法没有变化,jsx是基于xhtml的js,而且是可以再jsx中写HTML的,
2、React中没有指令的概念,vue中的指令相比较就非常多,也很实用:v-if,v-model,v-show,v-for,v-on....
3、React想是想数据的双向绑定是要借助setData()方法的,但是Vue只需借助data()就可以了,相对React也更简单
相同点:
都是虚拟dom,二者都有很多生命周期中的钩子函数,二者都鼓励组件化开发SPA应用,父子组件传递数据也都是用props,子向父就要通过函数来传递,二者也都能构建自己的工具。

2. eventLoop原理

为了确保 异步代码 可以在 同步代码 执行后继续执行 (timeout)

3. 防抖和节流 

防抖和节流是针对响应跟不上触发频率这类问题的两种解决方案

防抖(设定timeout,函数设定的时间后执行)
function debounce(func,wait,immediate) {
    let timeout;

    return function () {
        let context = this;
        let args = arguments;

        if (timeout) clearTimeout(timeout);
        if (immediate) {
            var callNow = !timeout;
            timeout = setTimeout(() => {
                timeout = null;
            }, wait)
            if (callNow) func.apply(context, args)
        }
        else {
            timeout = setTimeout(function(){
                func.apply(context, args)
            }, wait);
        }
    }
}

节流(设定时间间隔,按间隔时间循环执行)
function throttle(func, wait ,type) {
    if(type===1){
        let previous = 0;
    }else if(type===2){
        let timeout;
    }
    return function() {
        let context = this;
        let args = arguments;
        if(type===1){
            let now = Date.now();

            if (now - previous > wait) {
                func.apply(context, args);
                previous = now;
            }
        }else if(type===2){
            if (!timeout) {
                timeout = setTimeout(() => {
                    timeout = null;
                    func.apply(context, args)
                }, wait)
            }
        }
    }
}

 4. 水平垂直居中的多种方式

1、position 元素已知宽度
2、position transform 元素未知宽度
3、flex布局
4、table-cell布局

5. promise、generator、async、await怎么使用,有什么区别

1、promise是一种新的写法,用来解决“回调地狱”的问题
//使用同步的写法,解决异步操作,。(异步-性能高,用户体验更好;同步-更简单,更方便)
    //使用方法:
    let pro = new Promise((reslove,reject)=>{
                $.ajax({
                    url:'1.txt',//1.txt文件中返回json {"a":12,"b":5}
                    dataType:'json',
                    success(json){
                        reslove(json)//成功会调用reslove函数
                    },
                    error(err){
                        reject(err) //失败调用reject函数
                    }
                })  
    })
    //调用方法:(当pro内部函数执行完成之后,就会调用then方法。then方法取代了AJAX中原本的成功与失败方法。)    
    pro.then((json)=>{
        alert("成功")
        },
        (err)=>{
            alert("失败")
        })
    //使用then()方法调用promise,参数为两个函数,第一个函数为成功,第二个函数为失败
    //调用方法(多次调用):
    Promise.all([pro,pro1,pro2]).then((arr)=>{
        alert("成功");
        let[a,a1,a2]=arr;
        },
        (err)=>{
            alert("失败")
        })//pro\pro1\pro2是三个Promise对象。
    //使用all()之后 需要参数对象内部函数全部执行完毕之后,才执行then,成功后返回一个数组,可以用解构赋值来接收为独立的数据。
    //当多个pro对象,有逻辑关系的情况下。需要使用async、await解决。
    //Promise.race()与Promise.all()的区别是,race()是 参数中ajax只要有一个完成即算完成。all()需要参数所有的ajax全部完成才执行成功

    //注:JQ中ajax的返回值就是一个Promise对象。所以ajax也有then方法,用来执行成功与失败。所以Promise.all()中的参数,可以直接放ajax。
    //Promise.all([$.ajax(xxx),$.ajax(xxx),$.ajax(xxx)]).then()//正常执行成功失败的方法。arr为三个ajax的返回数据。

2、generator 函数 (生成器函数)
Generator是协程在ES6的实现,最大的特点就是可以交出函数的执行权,懂得退让。
var fetch = require('node-fetch');

function* gen(){
  var url = 'https://api.github.com/users/github';
  var result = yield fetch(url);
  console.log(result.bio);
}

var g = gen();
var result = g.next();

result.value.then( data => return data.json).then (data => g.next(data))

3、Async/await:其实async函数就是Generator函数的语法糖
async用于声明一个function是异步的,await用于等待一个异步方法执行完成
//只要在函数前加上async即可 表明这是一个async函数。函数体中使用await代替yield。//调用直接运行函数名即可;
async function show(){}
//await 会判断返回的数据对象,如果不是一个异步操作他就不会停止,例如 await 12;就会直接运行不会出现暂停。
//await 后可以放promise、generator函数,或者另外一个async函数
//async 后的function可以省略,匿名函数 async ()=>{}
async function show(){
    let data = await $ajax(xxx);    
    let data1 = await $ajax(xxx);
    let data2 = await $ajax(xxx);
    console.log(data,data1,data2)
}
show()//data,data1,data2 的数据
//含有逻辑关系的异步
async function show(){
    let data = await $ajax(xxx);
    if(dataxxxx){//如果满足条件走data1
        let data1 = await $ajax(xxx);
        console.log(data1)
    }else{//否则走data2
        let data2 = await $ajax(xxx);
        console.log(data2)
    }
}
show()//输出对应逻辑的数据
//以上是async函数中 ajax返回正常的情况;当ajax返回出错时情况处理,直接在async函数中使用try{}catch(){}包含所有的await的ajax;
//loading层 的使用 直接在async函数中所有await之前开启loading层,之后关闭即可。


 6. 前端性能优化的方法

https://www.cnblogs.com/xiaohuochai/p/9178390.html


7. 实现一个路由

1、监听 hashchange ,hash 改变的时候,根据当前的 hash 匹配相应的 html 内容,然后用 innerHTML 把 html 内容放进 router-view 里面。
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="author" content="">
    <title>原生模拟 Vue 路由切换</title>
    <style type="text/css">
        .router_box,
        #router-view {
            max-width: 1000px;
            margin: 50px auto;
            padding: 0 20px;
        }
        
        .router_box>a {
            padding: 0 10px;
            color: #42b983;
        }
    </style>
</head>

<body>
    <div class="router_box">
        <a href="/home" class="router">主页</a>
        <a href="/news" class="router">新闻</a>
        <a href="/team" class="router">团队</a>
        <a href="/about" class="router">关于</a>
    </div>
    <div id="router-view"></div>
    <script type="text/javascript">
        function Vue(parameters) {
            let vue = {};
            vue.routes = parameters.routes || [];
            vue.init = function() {
                document.querySelectorAll(".router").forEach((item, index) => {
                    item.addEventListener("click", function(e) {
                        let event = e || window.event;
                        event.preventDefault();
                        window.location.hash = this.getAttribute("href");
                    }, false);
                });

                window.addEventListener("hashchange", () => {
                    vue.routerChange();
                });

                vue.routerChange();
            };
            vue.routerChange = () => {
                let nowHash = window.location.hash;
                let index = vue.routes.findIndex((item, index) => {
                    return nowHash == ('#' + item.path);
                });
                if (index >= 0) {
                    document.querySelector("#router-view").innerHTML = vue.routes[index].component;
                } else {
                    let defaultIndex = vue.routes.findIndex((item, index) => {
                        return item.path == '*';
                    });
                    if (defaultIndex >= 0) {
                        window.location.hash = vue.routes[defaultIndex].redirect;
                    }
                }
            };

            vue.init();
        }

        new Vue({
            routes: [{
                path: '/home',
                component: "<h1>主页</h1><a href='https://github.com/biaochenxuying'>https://github.com/biaochenxuying</a>"
            }, {
                path: '/news',
                component: "<h1>新闻</h1><a href='http://biaochenxuying.cn/main.html'>http://biaochenxuying.cn/main.html</a>"
            }, {
                path: '/team',
                component: '<h1>团队</h1><h4>全栈修炼</h4>'
            }, {
                path: '/about',
                component: '<h1>关于</h1><h4>关注公众号:BiaoChenXuYing</h4><p>分享 WEB 全栈开发等相关的技术文章,热点资源,全栈程序员的成长之路。</p>'
            }, {
                path: '*',
                redirect: '/home'
            }]
        });
    </script>
</body>

</html>

2、history路由主要是通过history.pushState()方法向浏览记录中添加一条历史记录,并同时触发js回调加载页面,history路由实现与hash路由的步骤类似,由于需要配置路由模式切换,页面中所有的a链接都采用了hash类型链接,history路由初始化时,需要拦截a标签的默认跳转


8. 数组最大差值

js方法一:
Array.prototype.outputMaxPrice  = function outputMaxPrice (array) {
  const item1 = Math.max.apply( Math, array );
  const item2 = Math.min.apply( Math, array );
  return item1 - item2;
}

const array = new Array;
array.outputMaxPrice ([1, 3, 63, 44])   //  62


js方法二:
var getMaxProfit = function(arr){
  // 定义两个变量,分别存贮最大值和最小值
  let maxNum = arr[0];
  let minNum = arr[0];
  for(let i = 0; i < arr.length; i++){
    if(arr[i] > maxNum){
      maxNum = arr[i];
    }
    if(arr[i] < minNum){
      minNum = arr[i];
    }
  }
  return maxNum - minNum;
}

getMaxProfit([1, 3, 63, 44])   // 62


9. CORS原理

相对JSONP,CORS支持POST提交,并且实施起来灰常简单,CORS原理只需要向响应头header中注入Access-Control-Allow-Origin,这样浏览器检测到header中的Access-Control-Allow-Origin,则就可以跨域操作了。
具体:https://www.cnblogs.com/keyi/p/6726089.html


10. select组件

编写一个选中框和一个下拉列表,点击选中框可以展示下拉,点击下拉选项,选中框展示点击的下拉选项,并将值赋值给点击事件,隐藏下拉列表


11. BFC的原理及应用场景

BFC,即Block Formatting Contexts(块级格式化上下文),它属于上述定位方案的普通流。
具有BFC特性的元素可以看做是隔离了的独立容器,容器里面的元素不会再布局上影响到外面的元素,并且BFC具有普通容器所没有的一些特性。
可以把BFC,理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部。

BFC 布局规则
内部的Box会在垂直方向,一个接一个地放置。
Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
BFC的区域不会与float box重叠。
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
计算BFC的高度时,浮动元素也参与计算

触发BFC
只要元素满足下面任一条件即可触发BFC特性:
body根元素
浮动元素:float除none以外的值
绝对定位元素:position(absolute、fixed)
display为inline-block、table-cells、flex
overflow除了visible以外的值(hidden、auto、scroll)


12.从浏览器输入url直到页面渲染,期间有哪些步骤

1、DNS解析URL的过程
2、浏览器发送请求与服务器交互的过程
3、浏览器对接收到的html页面渲染的过程

一、DNS解析URL的过程
      DNS解析的过程就是寻找哪个服务器上有请求的资源。因为ip地址不容易记忆,一般会使用URL域名(如www.baidu.com)作为网址。DNS解析就是将域名翻译成IP地址的过程。

具体过程:

    1)浏览器缓存:浏览器会按照一定的频率 缓存DNS记录
    2)操作系统缓存:如果浏览器缓存中找不到需要的DNS记录,就会取操作系统中找
  3)路由缓存:路由器也有DNS缓存
  4)ISP的DNS服务器:ISP有专门的DNS服务器应对DNS查询请求
  5)根服务器:ISP的DNS服务器找不到之后,就要向根服务器发出请求,进行递归查询

二、浏览器与服务器交互过程

  1)首先浏览器利用tcp协议通过三次握手与服务器建立连接
  http请求包括header和body。header中包括请求的方式(get和post)、请求的协议 (http、https、ftp)、请求的地址ip、缓存cookie。body中有请求的内容。
  2)浏览器根据解析到的IP地址和端口号发起http的get请求.
  3)服务器接收到http请求之后,开始搜索html页面,并使用http返回响应报文
  4)若状态码为200显示响应成功,浏览器接收到返回的html页面之后,开始进行页面的渲染

三、浏览器页面渲染过程

  1)浏览器根据深度遍历的方式把html节点遍历成dom 树
  2)将css解析成CSS DOM树
  3)将dom树和CSS DOM树构造成render树
  4)JS根据得到的render树 计算所有节点在屏幕中的位置,进行布局(回流)
  5)遍历render树并调用硬件API绘制所有节点(重绘)

补充: 构造render渲染树的过程
从DOM树的根节点开始遍历每个可见的节点。
对于每个可见的节点,找到CSS树中的对应的规则,并且应用他们。
根据每个可见的节点及其对应的样式,组合生成渲染树。

13. 改变this的几种方式;apply/call/bind 有什么区别

对于 apply、call 二者而言,作用完全一样,只是接受参数的方式不太一样。
何时使用 apply、call,何时使用 bind 呢。简单的一个栗子:
var obj = {
    x: 81,
};
  
var foo = {
    getX: function() {
        return this.x;
    }
}
  
console.log(foo.getX.bind(obj)());  //81
console.log(foo.getX.call(obj));    //81
console.log(foo.getX.apply(obj));   //81
  三个输出的都是81,但是注意看使用 bind() 方法的,他后面多了对括号。

  也就是说,区别是,当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。

  再总结一下:

apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
apply 、 call 、bind 三者都可以利用后续参数传参;
bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。

14. webpack配置项都有哪些,其中loader和plugin有什么区别

webpack配置项主要包括以下几个:
var config = {
    entry: [
    ],
    output: {
    },
    resolve: {
    },
    module: {
    },
    plugins: [
    ]
}
entry:入口,定义要打包的文件
output:出口,定义打包输出的文件;包括路径,文件名,还可能有运行时的访问路径(publicPath)参数
module: webpack将所有资源都看做是模块,而模块就需要加载器;
resolve:定义能够被打包的文件,文件后缀名
plugins:定义额外的插件

loader 和 plugin主要区别
loader 用于加载某些资源文件。 因为webpack 本身只能打包commonjs规范的js文件,对于其他资源例如 css,图片,或者其他的语法集,比如 jsx, coffee,是没有办法加载的。 这就需要对应的loader将资源转化,加载进来。从字面意思也能看出,loader是用于加载的,它作用于一个个文件上。

plugin 用于扩展webpack的功能。它直接作用于 webpack,扩展了它的功能。当然loader也时变相的扩展了 webpack ,但是它只专注于转化文件(transform)这一个领域。而plugin的功能更加的丰富,而不仅局限于资源的加载。


15. Array的方法

增删的方法:
push() 插入数组末尾,返回数组长度
unshift() 插入数组开头,返回数组长度
pop() 删除数组末尾,返回删除项
shift() 删除数组开头,返回删除项

重排序方法:
reverse() 将数组翻转
sort() 将数组按升序重排序

截取/合并:
concat() 合并,将添加的项合并到数组尾部 ,返回合并后的数组 (不改变原数组)
slice() 截取数组片段,eg:arr.slice(1,4),返回截取的数组(不改变原数组)
splice() 删除截取的片段,eg:arr.splice(1,4),返回截取后的数组

位置方法:
indexOf()
lastIndexOf() 

迭代方法:
every() 对数组中的每一项都执行给定的函数,同时成立时,则返回true
filter() 对数组中的每一项都执行给定的函数,返回函数执行为true的项组成的数组
forEach() 对数组中的每一项执行给定的函数,但无返回值
map() 对数组中的每一项执行给定的函数,返回每次函数调用的结果组成的数组
some() 对数组中的每一项执行给定的函数,当执行项中有一个是true,则返回true

归并方法:
reduce()
reduceRight()

17. 异步有哪些场景,怎么解决异步

主流的解决方法主要有以下几种:

回调函数
事件触发
发布/订阅者模式
promise
generate

18.localStorage、sessionStorage 区别;应用业务场景

https://www.cnblogs.com/leftJS/p/10927013.html


19.如何区分行内、块级元素

块级元素 :总是以一个块的形式表现出来,并和同级的兄弟一次垂直排列,左右撑满,比如<li>,<p><hn>,总是不会排在同一行,而是和相邻的<li>垂直排列,简单来说,就是标准文档流下它会自动换行,并不会挤在一行上.就像柜台买票排队,按照正规流程,应该是自动排队,并不能挤在一条上在同一个窗口服务,那不是乱套了吗?但是特殊情况下还是有的(这个就是靠浮动来实现)

行内元素: 相邻元素之间横向排列,到最右端自动折行,比如<span>,<a>,也是运用他们的时候会自动挤到同一行上,除非空间不够了,才会去下一行.


20.ES6+新特性,经由babel编译后的代码,实现promise/promise.all/async/await 

es6新特性:https://www.cnblogs.com/minghui007/p/8177925.html
1、 变量声明-let 与 const
let为JavaScript新增了块级作用域。
2、模版字符串
使用 反引号``(键盘上esc下面那个键) 将整个字符串包裹起来,而在其中使用 ${} 来包裹一个变量或者一个表达式
3、解构(destructuring)赋值
数组以序列号一一对应,这是一个有序的对应关系。
对象根据属性名一一对应,这是一个无序的对应关系。
4、展开运算符(spread operater)
在ES6中用...来表示展开运算符,它可以将数组方法或者对象进行展开。上栗子
5、arrow function箭头函数
6、函数参数的默认值
function add(x = 20) {
    return x ;
}
7、对象字面量({})扩展
ES6针对对象字面量做了许多简化语法的处理
const person = {
  name,
  age
}
let obj = {  
    ['h'+'ello']() {  
        return 'hi';  
     }  
}; 
8、class、extend、super
class、extend、super这三个特性涉及了ES5中最令人头疼的的几个部分:构造函数、继承,原型...
ES6提供了更接近传统语言的写法,引入了Class(类)这个概念。新的class写法让对象原型的写法更加清晰、更像面向对象编程的语法,也更加通俗易懂。
9、模块的 Import 和 Export
import 用于引入模块,export 用于导出模块。

经由babel编译后的代码:https://blog.csdn.net/i10630226/article/details/78013968

21.vuex、redux流程有什么区别,哪种更好,如果你设计,能有什么改进
22.js的构造函数、工厂模式、单例模式、观察者模式、装饰器模式

23.选一到两个你比较满意或者印象深刻的项目,讲讲你在其中起到的作用,遇到过什么比较有挑战的问题,如何解决

 24.vue、react、es6 等等 最近有什么新进展?
25.vue的观察者模式,有什么缺陷吗,尤雨溪vue3.0打算怎么优化,或者有什么其他改进点

 26.变量提升、函数提升的code题

27.SSR服务端渲染了解过吗
28.vue和react对diff算法的优化有哪些;你觉得最新的这些框架和以前jquery相比有什么优势

29.bfs 和 dfs 算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值