美文网首页
前端面试知识点整理(附答案)

前端面试知识点整理(附答案)

作者: 丨Alan | 来源:发表于2019-06-27 09:41 被阅读0次

    知识点目录基于 https://segmentfault.com/a/1190000018603454
    根据个人理解对每个知识点附上的答案,有错误欢迎大家指出。

    html

    1. html语义化标签的理解、结构化的理解
    • 大部分情况,采用div+css就可以实现静态页面,但是这样的布局会导致文档结构不够清晰,而且不利于浏览器的读取。而如果采用语义强的标签,比如用H系列标签表示标题,strong表示强调等,这样就能提升网站的可读性,便与团队开发和维护。
    • 结构化也是为了增加代码可读性,提升网页质量,比如header、footer表示文档页眉页脚,nav表示导航等。
    2. 能否写出简洁的html结构
    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>标题</title>
        </head>
        <body>
            内容
        </body>
    </html>
    
    3. SEO优化
    • h1标签页面只能出现一次,权重最高
    • 减少div标签的使用,尽量使用语义化强的标签
    • 注重meta标签的使用,比如name属性设置为description、keywords等,对搜索引擎的索引有帮助。
    • 注重a标签和img标签的链接(title)和图片说明(alt)
    • 减少http请求次数,合理设置http缓存(合并css、js、图片等外部资源文件)
    • 减少图片数量,小图标可以用精灵图的方式
    • 启用文件压缩等
    4. html5新增了哪些特性
    • 增加语义标签

    header、footer、nav、section文档中的一节、article页面的独立内容区域、aside页面侧边栏内容、detailes文档某个细节部分、summary包含details元素的标题、dialog对话框

    • 增强表单

    提供input更多输入类型,如color、date、email、number、range、tel、week、url、search等;新的表单元素datalist(其id属性与input的list属性绑定,实现选项列表输入);新表单元素keygen、output等;新增placehoder、required、pattern、min、max、step、height、width、autofocus、multiple属性。

    • 提供audio、video标签
    • 新增canvas容器标签,结合js绘制图形、路径、文本等。
    <script>
      var c=document.getElementById("myCanvas");
      var ctx=c.getContext("2d");
      ctx.fillStyle="#FF0000";
      ctx.fillRect(0,0,150,75);
    </script>
    还有moveTo(x,y)线条开始坐标、lineTo(x,y)线条结束坐标;
    fillText(text,x,y)实心文本、strokeText(text,x,y)心文本;
    createLinearGradient(x,y,x1,y1) - 创建线条渐变
    createRadialGradient(x,y,r,x1,y1,r1) - 创建一个径向/圆渐变
    drawImage(image,x,y) - 将图片放在画布上等
    
    • 新增API
    网络:
        检测网络状态: window.navigator.onLine
        事件监听:online和offline 监听连上网络和断开网络
    地理定位:
        获取当前地理信息:
        window.navigator.geolocation.getCurrentPosition(
            successCallback, 
            errorCallback, 
            options
        )
        重复获取当前地理信息:
        window.navigator.geolocation.watchPosition(
            successCallback, 
            errorCallback, 
            options
        )
        成功的回调参数:
            position.coords.latitude 纬度
            position.coords.longitude经度
    web存储:
        sessionStorage(生命周期为关闭浏览器) 5M
        localStorage(永久生效,除非手动删除) 20M
    全屏:
        允许用户自定义网上任一元素全屏显示:
            requestFullScreen() 开启全屏
            cancelFullScreen() 关闭全屏
    文件读取:
        FileList对象,input上传文件后返回该对象
        FileReader对象:
            读取:readAsDataURL(file.files[0])
            监听: onload
    拖拽:
        给元素设置draggable="true",其中img和a标签默认可拖拽
        事件监听:
            拖拽元素:
            drag: 拖拽过程中一直调用
            dragstart: 拖拽开始调用
            dragleave: 鼠标离开拖拽元素调用
            dragend: 拖拽结束调用
            目标元素:
            dragenter:拖拽元素进入时调用
            dragover:停留在目标元素上时调用,注意阻止浏览器默认行为(event.preventDefault())
            drop:当在目标元素上松开鼠标时调用
            dragleave:当鼠标离开目标元素时调用
        可以通过dataTransfer拿到当前的拖拽进来的文件列表
    多媒体:
        load()、play()、pause()
    

    css

    1. css选择器
    • 标签~
    • 类~
    • id~
    • 并集~(逗号)
    • 交集~(标签连写)
    • 后代~(空格)
    • 子~(>)
    • 相邻兄弟~(+)
    • 兄弟
    • 通配符~(*)
    • 属性~([])
    • 序~(:first-child、:last-child、nth-child等)
    • 伪类~
    • 伪元素~
    css3新增的属性和选择器:
        属性选择器、伪类选择器、反选伪类(:not())
        box-shadow、border-image、
        text-overflow(clip|ellipsis|string)、word-wrap、border-radius、opacity、
        box-sizing、resize、
        background-size、background-origin、background-clip
        transform、trasition、animation
    
    2. 三大特性
    • 继承性(父元素设置属性,子元素默认也生效。color-|font-|text-|line-开头的可以继承)
    • 层叠性(多个选择器选中同一元素,修改同一属性时。觉得如何生效需要根据优先级判断)
    • 优先级
    3. BFC机制
    • BFC(Block Formatting Context)概念

    格式化上下文,指一个独立的渲染区域或者说是一个隔离的独立容器

    • 形成BFC的条件
    1. 浮动元素,float除none以外的值
    2. 定位元素,position(absolute、fixed)
    3. display(inline-block、table-cell、table-caption)
    4. overflow(除visible以外的值)hidden、auto、scroll
    5. body根元素
    • BFC的特性
    1. 是个独立容器,内部元素不会影响外面元素
    2. 不被浮动元素覆盖
    3. 父元素是BFC时,不会被子元素的margin挤下来
    4. BFC容器的高度,内部浮动元素也参与计算(比如overflow:hidden清除浮动,可以让内部浮动元素也能撑开父元素高度)
    4. 盒模型

    将元素类比为一个盒子,有外边距、边框、内边距、宽度、高度五个元素决定齐所占的元素空间大小

    常见问题:

    • padding内边距会导致元素的宽度和高度变化

    可通过box-sizing:border-box锁定元素宽高;

    content-box 元素的宽高 = 边框 + 内边距 + 内容宽高
    border-box 元素的宽高 = width/height的宽高
    
    • margin合并现象(默认垂直方向的外边距不会叠加,会出现合并,谁的边距大就按照谁的来);

    将其中一个元素放入一个BFC模式的元素内(不推荐,会改变文档结构);一般会给其中一个元素设置margin-bottom直接给够距离

    • margin塌陷现象,内部盒子的外边距会将父盒子顶下来

    利用BFC机制,比如父盒子设置overflow:hidden;

    • 宽度高度问题
    内容宽高 = width/height
    元素宽高 = 边框+内边距+width/height;设置box-sizing:border-box后值为:width/height
    元素空间的宽高:外边距+边框+内边距+width/height
    
    5.css模块化开发(css预处理器:stylus/scss/less)

    css预处理器方便开发,无需考虑浏览器兼容问题,代码模块化、清晰简洁

    scss 是 sass3 引入新的语法,其语法完全兼容 css3,并且继承了 sass 的强大功能。sass 和 scss 其实是同一种东西,我们平时都称之为 sass,两者之间不同之处有以下两点:1.文件扩展名不同(.sass/.scss);2.语法书写方式不同,sass 是以严格的缩进式语法规则来书写,不带大括号({})和分号(;),而 scss 的语法书写和我们的 css 语法书写方式非常类似。

    6. 屏幕适配以及页面自适应
    • 允许网页宽度自动调整
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    
    • 宽度百分比
    • 相对字体rem/em
    • 流动布局,利用float或者display:fixed等
    • 使用css media模块
    @media screen and (min-width: 768px) and (max-width: 1024px)
        ...
    
    • 图片自适应,max-width/min-width等
    7. 布局相关
    • 标准文档流(padding+margin)+浮动+定位
    • 百分比布局
    • flex弹性布局
    • grid栅格布局(display:grid),使用框架中的类名来替代,本质上还是百分比布局

    JavaScript

    1. 变量数据类型及检测:基本 + 引用
    基本:String、Number、Boolean、Undefined、Null
    引用:Object(Array、Function...)
    检测:
       typeof(用于基本类型;typeof null返回object;typeof []返回object)
              变量 === null ? 'null' : typeof 变量
       instanceof(用于引用类型;不适用undefined和null)
       (变量).constructor(不适用undefined和null)
       Object.prototype.toString.call(),可以解决判断所有类型
    
    2. 运算符
    • 算术运算符(+、-、*、/、%、++、--)
    • 赋值运算符(=、+=、-=、*=、/=、%=)
    • 条件运算符(三元表达式)
    • 逻辑运算符(!、&&(短路,第一个值为false,第二个值不用检测了)、||(短路,第一个值为true,第二个值不用检测了))
    • 比较运算符(双等于、===、!=、>、<、>=、<=)
    • 位运算符(非~、按位与&、按位或|、异或^、左移<<、有符号右移>>、无符号右移>>>)
    • 显示类型转换(Boolean()、Number()、String()、Object()等)
    • 隐示类型转换
    +运算符的一个值如果是字符串,它会把另一个值转为字符串拼接
    一元+,会将值试图转为数字,如 +"5"
    一元!,会将值试图转为boolean,再取反
    在做比较运算时,也会发生很多隐示转换:
        对象转字符串再转数字
        布尔转数字
        字符串转数字
    
    • 条件语句(if、switch case);循环语句(for、while、do while、foreach、for of、for in等)
    3. 函数
    函数定义:
        function example(param){}
        const example = function(param){}
        (function (param){})()
        const example = new Function('param', '')
        (param) => {} 箭头函数内的this与外层的this一样,箭头函数不能提升
    函数调用:
        函数名调用 example(param)相当于window.example(param)
        作为方法调用,比如某个对象中的行为 obj.example(param)
        构造函数调用 const exampleObj = new example(param); exampleObj.属性/行为
        作为函数方法调用函数call()、apply():
            obj = example.call(obj, param1, param2)
            obj = example.apply(obj, paramArray)
    
    call和apply详解:
    
    在javascript中,call和apply都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部this的指向。
    function fruits() {}
    fruits.prototype = {
        color: "red",
        say: function() {
            console.log("My color is " + this.color);
        }
    }
    var apple = new fruits;
    apple.say();    //My color is red
    
    banana = {
        color: "yellow"
    }
    apple.say.call(banana);     //My color is yellow
    apple.say.apply(banana);    //My color is yellow
    所以,可以看出call和apply是为了动态改变this而出现的,当一个object没有某个方法(本例子中banana没有say方法),
    但是其他的有(本例子中apple有say方法),我们可以借助call或apply用其它对象的方法来操作。
    
    二者区别:
        func.call(this, arg1, arg2); 若干个参数
        func.apply(this, [arg1, arg2]); 数组参数
        
    常用实例:
    数组追加:
        var array1 = [12 , "foo" , {name:"Joe"} , -2458]; 
        var array2 = ["Doe" , 555 , 100]; 
        Array.prototype.push.apply(array1, array2); 
        // array1 值为  [12 , "foo" , {name:"Joe"} , -2458 , "Doe" , 555 , 100]
    获取数组中的最大值和最小值:
        var numbers = [5, 458 , 120 , -215 ];
        var maxInNumbers = Math.max.apply(Math, numbers), //458
            maxInNumbers = Math.max.call(Math, 5, 458, 120, -215); //458
        // number 本身没有 max 方法,但是 Math 有,我们就可以借助 call 或者 apply 使用其方法。
    验证是否是数组(前提是toString()方法没有被重写过):
        functionisArray(obj){ 
            return Object.prototype.toString.call(obj) === '[object Array]' ;
        }
    真伪数组转换:
        真转伪:[].push.apply(obj, arr);
        伪转真:[].slice.call(obj);
    bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用
    
    • 实参形参传值问题
    基本类型,按值传递(函数内部修改形参值,不会影响外部实参值)
    引用类型,按对象共享传递
        var obj = {};
        function f(o) {
            o.name = 'li';
        }
        f(obj);
        console.log(obj.name); //li  被修改了
    
        var obj = {};
        function f(o) {
            o = [];
        }
        f(obj);
        console.log(obj); //{}  没有修改
        调用函数传参时,函数接受对象实参引用的副本(既不是按值传递的对象副本,也不是按引用传递的隐式引用)。
        它和按引用传递的不同在于:在共享传递中对函数形参的赋值,不会影响实参的值。如下面例子中,不可以通过修改形参o的值,来修改obj的值。
        也就是说不可以改变引用类型的指针,只可以改变这个对象的属性
    
    4. 字符串、数组、对象常用API
    • 数组方法
    concat()拼接数组,参数是任意个值或者数组,返回新数组,不影响原数组
    join()将数组的值用指定分隔符转成字符串,不传参默认为逗号,返回新值,不影响原值
    pop()删除并返回数组最后一个元素
    push()向数组末尾添加一个或多个元素,返回数组新长度
    shift()删除并返回数组第一个元素
    unshift()想数组开头添加一个或多个元素,返回数组新长度
    
    slice(start,end)包含头不包含尾,返回新值对原值没有影响
    splice(index,howmany,item1...,itemX)
        可用于替换,删除,添加;
        howmany表示要删除的个数,返回被删除的值组成的数组,原数组被修改
        
    sort()对数组元素排序,修改原值
    reverse()点到数组中元素的顺序,修改原值
    
    every()是对数组中的每一项运行给定函数,如果每一项都返回true,则返回true
    some()是对数组中的每一项运行给定函数,如果对任一项返回true,则返回true
    filter()是对数组中的每一项运行给定函数,返回该函数返回true的项组成数组
    map()是对数组中的每一项运行给定函数,返回每次函数调用的结果组成数组
    reduce()从数组元素中计算出一个值
    arr.indexOf('')查找数组,判断数组中是否含有某一项
    
    • 字符串
    三个字符方法:
    charAt()返回给定位置的字符
    charCodeAt()返回给定位置的字符编码
    str[index]直接用方括号加索引也能返回指定位置的字符,IE7及更早版本不支持
    
    操作字符串方法:
    concat()用于拼接字符串,可传任意个参数
    slice(start,end)包含头不包含尾,返回新值对原值没有影响
    substring(start,end)包含头不包含尾,返回新值对原值没有影响
    substr(start,num)第二个参数为个数,返回新值对原值没有影响
    
    字符串位置方法:
    indexOf()从前往后找、lastIndexOf()从后往前找
    
    大小写:
    toLowerCase()、toLocaleLowerCase()、toUpperCase()、toLocaleUpperCase()
    都是返回新值对原值没有影响
    
    字符串的模式匹配方法:
    match()参数为正则表达式或者RegExp对象,返回匹配的数组
    search()返回字符串中第一个匹配项的索引,如果没找到就返回-1
    replace(egexp/substr, replacement/function),返回新值对原值没有影响
    split()基于分隔符分割字符串,返回新数组对原值没有影响
    
    trim()删除字符串前后所有空格,返回新值对原值没有影响
    
    5. 正则表达式
    格式:/正则表达式主体/修饰符(可选)
    \d: 0-9任意一个数字
    \w: 数字、字母、下划线 0-9 a-z A-Z _
    \s: 空格或者空白
    (): 分组
    [a-z]: 区间内任意一个
    *: 0到多个
    +: 1到多个
    {n}: 正好n次
    {n,m}: n-m次
    比如手机:/1[34578]\d{9}/
    
    6. 作用域、作用域链、闭包
    • 作用域
    全局作用域、函数作用域
    ES6引入let和const关键字,随即带来块级作用域的概念
    
    • 作用域链
    对象有一个内部属性[[Scope]],该属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链。
    js解析某个变量时,会从代码嵌套的最内层开始,如果没找到,会顺着作用域链向上查找。
    
    • 闭包
    函数内部返回一个函数
    对外部暴露指定行为,但还是能用到自己作用域内的变量
        function greet(){
            name = 'Alan';
            return function() {
                console.log('Hi ' + name);
            }
        }
        greet()();
    私有作用域
        (function () {
            // private scope
        )()
    模块模式
        var Module = (function () {
            function _privateMethod() {}
            return {
                publicMethod: function() {
                    // can call privateMethod();
                }
            }
        })()
    
    7. 构造函数、原型、原型链、继承
    • 构造函数、原型和实例之间的关系
    构造函数的prototype指向一个原型对象,
    原型对象的constructor指回构造函数,
    实例的内部指针__proto__指向原型对象。
    通过调用构造函数产生的实例,都有一个内部属性,指向了原型对象。所以实例能够访问原型对象上的所有属性和方法
    
    例子:
        function Dog (name) {
            this.name = name;
        }
        Dog.prototype.speak = function () {
          alert('wang');
        }
        var doggie = new Dog('jiwawa');
        doggie.speak();  //wang 
        Dog.prototype.constructor == Dog  //true
    
    graph LR
        C[实例] --> B
        A[构造函数Dog] --> B[Dog的原型对象]
        B --> A
    
    • 原型链、继承
    //定义一个 Animal 构造函数,作为 Dog 的父类
    function Animal () {
        this.superType = 'Animal';
    }
    Animal.prototype.superSpeak = function () {
        alert(this.superType);
    }
    function Dog (name) {
        this.name = name;
    }
    //改变Dog的prototype指针,指向一个 Animal 实例
    Dog.prototype = new Animal();
    Dog.prototype.speak = function () {
      alert(this.type);
    }
    var doggie = new Dog('jiwawa');
    doggie.superSpeak();  //Animal 
    
    如果将Dog的prototype指针指向另一个Animal的实例,那么Dog的实例就能调用Animal的属性和方法。
    
    8. 函数上下文(this指向)
    规律一:函数名加圆括号直接调用,函数上下文是 window 对象。
    规律二:函数如果作为一个对象的方法,对象使用点方法进行调用,那么函数的上下文就是这个对象。
    规律三:函数是事件处理函数,那么函数的上下文就是触发这个事件的对象。
    规律四:函数被定时器调用时,上下文是 window 对象。
    规律五:数组中存放的函数,被数组索引调用,函数上下文就是这个数组。
    
    9. js的运行机制、事件队列和循环
    JS单线程(主线程)
           ↓
    单线程导致任务需要排队,如果前一个任务耗时很长,后面的就一直等着。
    如果排队是因为计算了大,CPU忙不过来,倒也算了。
    很多时候没事因为IO设备慢(比如Ajax操作从网络读取数据)
           ↓
    同步任务和异步任务
        同步:在主线程上排队执行的任务,前一个完成,才执行后一个。
        异步:不进入主线程,而进入“任务队列”,只有“任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
    只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。这个过程会不断重复
           ↓
    "任务队列"是一个事件(消息)的队列,IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈"了。主线程读取"任务队列",就是读取里面有哪些事件。
    "任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。
    所谓"回调函数"(callback),就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。
    主线程的读取过程基本上是自动的,只要执行栈一清空,"任务队列"上第一位的事件就自动进入主线程。但是,由于"定时器"功能,主线程首先要检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。
           ↓
    主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。
    执行栈中的代码(同步任务),总是在读取"任务队列"(异步任务)之前执行。
    
    10. Ajax(Asynchronous JavaScript and XML)原理
    Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
    
    var xmlHttp;
    if (window.XMLHttpRequest) {// IE7及以上
        xmlHttp = new XMLHttpRequest();
    } else {
        xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
    }
    xmlHttp.open('GET/POST', url, true/false);
    // 如果是post,需要设置请求头
    xmlHttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    xmlHttp.send(); // 如果是post,需要传参数,参数为空就传null;
    xmlHttp.onreadystatechagne = function() {
        if (xmlHttp.readyState == 4) {
            if (xmlHttp.status >= 200 && xmlHttp.status < 300 || xmlHttp.status == 304) {
                // 成功回调函数...
            } else {
                // 失败回调函数...
            }
        }
    };
        
    相关知识点:
        GET 更简单更快,无法发送大数据,无法缓存
        POST 更大更稳定,可发大数据,可缓存
        readyState(0: 请求未初始化
                   1: 服务器连接已建立
                   2: 请求已接收
                   3: 请求处理中
                   4: 请求已完成,且响应已就绪)
       status(1字头:消息,代表请求已被接受,需要继续处理;
              2字头:成功;
              3字头:重定向;
              4字头:请求错误;
              5、6字头:服务器错误)
              常见:200成功、304缓存、404未找到页面、500服务器错误
    
    11. Axios原理
    普通使用:
        import axios from 'axios'
        axios.get/post(url, params).then(function(){}).catch(function(){})
    自定义axios常见使用方式:
        let myAxios = axios.create({
            baseURL: '',
            timeout: 30000,
            headers: {},
            ...
        })
        // 请求拦截器
        myAxios.interceptors.request.use(
            function (config) {
                // 发送请求之前做些什么,比如token
                if (store.state.Token) {
                    config.headers.Authorization = '前缀' + store.state.Token
                }
                reutrn config
            },
            function (error) {
                // 对请求错误,做些什么
                return Promise.reject(error)
            }
        )
        // 响应拦截器
        myAxios.interceptors.response.use(
            function (response) {
                // 对响应数据做点什么
                return response.data
            },
            function (error) {
                // 对响应错误做点什么, 比如后台返回token失效的状态码,就需要跳转login
                if (error && error.response) {
                    switch (error.response.status) {
                        case 400: 
                            error.message = '请求出错'
                            break
                        case 401:
                            alert('token失效,重新登录')
                            store.commit('loginOut')
                            setTimeout(() => {
                                window.location.reload()
                            }, 1000)
                            return
                    }
                } else {
                    error.message = '连接服务器失败'
                }
                alert(error.message)
                return Promise.reject(error.response)
            }
        )
    
    12. 异步编程
    • 回调函数
    • 事件监听
    • ES6/Promise对象(避免层层嵌套的异步回调,代码更清晰)
    • ES6/Generator函数
    • ES7/async和await

    浏览器

    1. 内核

    Trident(IE)、Gecko9(火狐)、Blink(Chrome、Opera)、Webkit(Safari)

    2. 功能模块
    HTML解释器
        CSS解释器
        图层布局计算模块:布局计算每个对象的精确位置和大小
        视图绘制模块:进行具体节点的图像绘制,将像素渲染到屏幕上
        JavaScript引擎:编译执行JS代码
    
    3. 运行机制
    运行机制:
        浏览器使用http/https向服务的请求页面
            ↓
        解析HTML,构建DOM树
            ↓
        计算DOM树上的CSS
            ↓
        (排版)根据CSS属性渲染元素,得到内存中的位图
            ↓
        (可选步骤)对位图进行合成,提升后续绘制速度
            ↓
        绘制到界面上
    
    4. 渲染原理
    解析HTML,生成DOM树(DOM)
    解析CSS,生成CSSOM树(CSSOM)
    将DOM和CSSOM合并,生成渲染树(Render-Tree)
    计算渲染树的布局(Layout)
    将布局渲染到屏幕上(Paint)
    
    5. 浏览器交互:BOM和DOM相关webApi、监听事件
    JavaScript分三个部分:
        ECMAScript标准 --- 基本语法
        DOM --- 文档对象模型,操作页面元素的
        BOM --- 浏览器对象模型,操作浏览器的
    浏览器顶级对象: window
    页面顶级对象: document
    页面中所有内容都属于浏览器
    
    • BOM(Browser Object Model)浏览器对象模型
    BOM是独立于内容的、可以与浏览器窗口进行互动的对象结构,其由多个对象组成,其中代表浏览器窗口的Window对象是其顶层对象。
    可刷新浏览器、后退、前进、在浏览器中输入URL等。
    alert()、prompt()、confirm()
    onload()、onunload()
    setTimeout()、clearTimeout()、setInterval()、clearInterval()
    loaction、history、navigator
    
    • DOM(Document Object Model)文档对象模型
    document.
        getElementById()
        getElementsByTagName()
        getElementsByName()
        getElementsByClassName()
        querySelector()
        createElement()
        appendChild()
    
    • 监听事件
    addEventListener("事件名","事件处理函数","布尔值false冒泡,true捕获")
    removeEventListener("事件名","事件处理函数","布尔值")
    preventDefault()阻止默认事件
    stopPropagation()阻止事件冒泡
    其他常用事件:
        onclick、ondbclick、
        onmousedown、onmouseup、onmouseout、onmousemove、onmouseover
    
    • 事件代理(事件委托)
    原理:利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件
    window.onload = function(){
      var oUl = document.getElementById("ul1");
      oUl.onclick = function(ev){
        var ev = ev || window.event;
        var target = ev.target || ev.srcElement;
        if(target.nodeName.toLowerCase() == 'li'){
            alert(target.innerHTML);
        }
      }
    }
    
    6. 缓存机制
    强缓存:用户发送的请求,直接从客户端缓存中获取,不发送请求到服务器,不与服务器发生交互行为。
        协商缓存:用户发送的请求,发送到服务器后,由服务器判定是否从缓存中获取资源。
        两者共同点:客户端获得的数据最后都是从客户端缓存中获得。
        两者的区别:从名字就可以看出,强缓存不与服务器交互,而协商缓存则需要与服务器交互。
    
    7. 跨域
    为什么会跨域:浏览器的同源策略(阻止不同协议或者域名或者端口的请求)
    解决方法:
        JSONP(只能发GET请求)
        空iframe加form
        CORS(跨域资源共享):响应头设置Access-Control-Allow-Origin等...
        代理
        ...
    

    关于网络协议

    1. HTTP协议
    HTTP(Hyper Text Transfer Protocol)超文本传输协议:
        基于TCP/IP通信协议传递数据,用于从万维网服务器传输超文本到本地浏览器的传送协议
    主要特点:
        简单快速、灵活、无连接(完成请求就断开链接)、无状态、支持B/S C/S
    
    • URL
    HTTP使用统一资源标识符URI来传输数据和建立连接,统一资源定位符URL是URI的一种特殊类型
    URL:协议+域名+端口+虚拟目录+文件名+锚(#)+参数(?)
    
    • Request
    请求行(请求方法 URL 协议版本)
    请求头(头部字段名 值...)
    空行(一定有一个空行)请求数据
    请求数据
    
    • Response
    状态行(协议版本 状态码 状态消息)
    消息报头
    空行
    响应正文(服务器返回给客户端的文本信息)
    
    • 状态码
    1xx:指示信息--表示请求已接收,继续处理
    2xx:成功--表示请求已被成功接收、理解、接受
    3xx:重定向--要完成请求必须进行更进一步的操作
    4xx:客户端错误--请求有语法错误或请求无法实现
    5xx:服务器端错误--服务器未能实现合法的请求
    
    常见:
        200 OK:客户端请求成功
        400 Bad Request:客户端请求有语法错误,不能被服务器所理解
        401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 
        403 Forbidden:服务器收到请求,但是拒绝提供服务
        404 Not Found:请求资源不存在,eg:输入了错误的URL
        500 Internal Server Error:服务器发生不可预期的错误
        503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常
    
    • 请求方法
    GET、HEAD、POST、PUT、DELETE、CONNECT、OPTIONS、TRACE
    
    • HTTP工作原理
    建立TCP连接(三次握手),客户端连接服务器
        ↓
    发送HTTP请求
        ↓
    服务器接受请求,返回HTTP响应
        ↓
    释放TCP连接
        ↓
    浏览器解析HTML内容
    
    • GET和POST区别
    GET: 请求数据附在URL后,地址栏可见
    POST: 请求数据包在请求体中
    
    GET: 长度有限(2083字节)
    POST: 理论上不限制大小,服务器常会对POST数据大小进行限制
    
    GET: 数据明文,不安全
    POST: 安全
    
    2. cookie、session、token、localStorage、sessionStorage
    • Cookie
    客户端缓存技术
    浏览器的一种数据存储功能,由服务器生成,发送给浏览器,以键值方式存储,下次请求,会把cookie发送给服务器,过期时长由expire决定
    
    • Session
    会话缓存技术
    类似客户端的身份标识,由服务器生成,保存在服务器端,以键值方式存储,默认30分钟过期
    客户端每次像服务器发送请求,都带上身份标识,服务器就知道请求来自谁。客户端常用cookie方式保存标识
    
    • Token
    用户登录成功,服务器生成Token返回给客户端
    客户端保存Token
    客户端每次请求携带Token
    服务器校验Token
    
    • localStorage
    生命周期永久,除非手动清楚,存放大小一般5MB,存在客户端
    
    • sessionStorage
    当前会话有效,关闭浏览器清楚,存放大小5MBD,存在客户端
    

    关于ES6语法

    • 变量声明 let/const
    变量名不自动提示,提供块级作用域
    
    • 箭头函数
    () => {}
    箭头函数中没有this,如果在箭头函数内使用this,该this是外层的this
    
    • 模板字符串
    使用``将字符串包裹,在其中可以使用${}来包裹一个变量或表达式
    
    • 解析结构
    数组以序列号对应,对象根据属性名对应
    eg: 
        // es5
        var loading = props.loading;
        var clicked = props.clicked;
        // es6
        const { loading, clicked } = props;
        
        // es6
        const arr = [1, 2, 3];
        const [a, b, c] = arr;
        // es5
        var arr = [1, 2, 3];
        var a = arr[0];
        var b = arr[1];
        var c = arr[2];
    
    • 函数默认参数
    // es5
    function add(x, y) {
        var x = x || 20;
        var y = y || 30;
        return x + y;
    }
    console.log(add());
    
    // es6
    function add(x = 20, y = 30) {
        return x + y;
    }
    console.log(add());
    
    • 展开运算符
    使用...可以将数组或者对象进行展开
    const arr1 = [1, 2, 3];
    const arr2 = [...arr1, 10, 20, 30];
    // 这样,arr2 就变成了[1, 2, 3, 10, 20, 30];
    
    const obj1 = {
      a: 1,
      b: 2, 
      c: 3
    }
    const obj2 = {
      ...obj1,
      d: 4,
      e: 5,
      f: 6
    }
    // 结果类似于 const obj2 = Object.assign({}, obj1, {d: 4})
    
    • 对象字面量与class
    当属性与值同名时,可简写
    const person = {
        name,
        age
    }
    
    // ES5
    // 构造函数
    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
    // 原型方法
    Person.prototype.getName = function() {
      return this.name
    }
    // ES6
    class Person {
      constructor(name, age) {  // 构造函数
        this.name = name;
        this.age = age;
      }
    
      getName() {  // 原型方法
        return this.name
      }
    }
    
    extends继承关键字、super()
    
    • Promise
    解决异步回调地狱问题
    promise.then(function(value) {
      // success 成功回调
    }, function(error) {
      // failure 失败回调
    });
    then方法返回一个新的Promise实例,因此支持链式写法,后面的then会等待前面then返回的Promise对象状态发生变化,然后决定调用resolve还是reject。
    .catch()
    .finally() ES2018引入, 不管promise最后状态,都会执行
    .all()将多个Promise实例包装成一个新的Promise实例,只有子实例状态都变为fulfilled,包装实例才变为fulfilled,如果其中一个是rejected,那么包装也是rejected。
    .race()同all()方法,相当于或操作,只要有一个实例状态改变,包装实例就会跟着改变
    .resolve()将现有对象转为Promise对象
    .reject()返回一个状态为rejected的Promise实例
    
    • Modules
    • Symbol(表示独一无二的值)
    • Set和Map
    Set类似于数组,但其成员的值都是唯一的,没有重复的值
    const s = new Set()
    const s1 = new Set([1,2,3,2,3])
    [...s]
    add(value):添加某个值,返回 Set 结构本身。
    delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
    has(value):返回一个布尔值,表示该值是否为Set的成员。
    clear():清除所有成员,没有返回值。
    
    类似于对象,也是键值对的集合,但是键不限于字符串,各种类型都可以当作键。
    const map = new Map()
    map.set(键,值)
    map.get(键)
    map.has(键)
    map.delete(键)
    map.clear()
    map.size
    
    遍历Set和Map:
        keys():返回键名的遍历器。
        values():返回键值的遍历器。
        entries():返回所有成员的遍历器。
        forEach():遍历 Map 的所有成员
    由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致
    
    • Proxy
    在目标对象之前架设一层“拦截”,外界访问该对象,都必须先通过这层拦截
    var proxy = new Proxy(target, handler)
    eg:
        var obj = new Proxy({}, {
          get: function (target, key, receiver) {
            console.log(`getting ${key}!`);
            return Reflect.get(target, key, receiver);
          },
          set: function (target, key, value, receiver) {
            console.log(`setting ${key}!`);
            return Reflect.set(target, key, value, receiver);
          }
        });
    get(target, propKey, receiver):
        拦截对象属性的读取,比如proxy.foo和proxy['foo']。
    set(target, propKey, value, receiver):
        拦截对象属性的设置,比如proxy.foo =v或proxy['foo']=v,返回一个布尔值。
    has(target, propKey):
        拦截propKey in proxy的操作,返回一个布尔值
    ...
    
    • Iterator和for...of循环
    Iterator作用:
        1. 为各种数据结构,提供一个统一的访问接口
        2. 使数据结构的成员能够按某种次序排列
        3. 创造了一种新的遍历命令for...of
    遍历器原理:创建一个指针指向数据结构(Array/Set/Map/String/TypedArry/arguments/NodeList)的初始位置,
               第一次调用指针对象的next方法,将指针指向第一个成员,第二次next指向第二个,以此类推,直到结束位置。
    for(let val of 数据结构){}
    
    • export 和 export default
    export与export default均可用于导出常量、函数、文件、模块等
    在一个文件或模块中,export、import可以有多个,export default仅有一个
    通过export方式导出,在导入时要加{ },export default则不需要
    export能直接导出变量表达式,export default不行
    

    Vue

    1. 指令
    v-text:绑定元素的文本内容 <span v-text="txt"></span>
    v-html:绑定元素的innerHTML <div v-html="html"></div>
    v-show:显示与隐藏,切换元素的display CSS属性
    v-if:Dom元素的销毁和重建
    v-for
    v-on:绑定事件监听器,缩写@;使用:v-on:click="handleClick()"
        修饰符:
        .stop - 调用 event.stopPropagation()。
        .prevent - 调用 event.preventDefault()。
        .capture - 添加事件侦听器时使用 capture 模式。
        .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
        .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。比如 @click.enter="handleEnter"
        .native - 监听组件根元素的原生事件。
        .once - 只触发一次回调。
        .left - (2.2.0) 只当点击鼠标左键时触发。
        .right - (2.2.0) 只当点击鼠标右键时触发。
        .middle - (2.2.0) 只当点击鼠标中键时触发。
        .passive - (2.3.0) 以 { passive: true } 模式添加侦听器
    v-bind:动态绑定一个或多个特性或组件prop到表达式,缩写":"; 比如 :class="{}"
        修饰符:
        .prop - 被用于绑定 DOM 属性 (property)。(差别在哪里?)
        .camel - (2.1.0+) 将 kebab-case 特性名转换为 camelCase. (从 2.1.0 开始支持)
        .sync (2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器。
    v-model:数据双向绑定
        修饰符:
        .lazy - 取代 input 监听 change 事件
        .number - 输入字符串转为有效的数字
        .trim - 输入首尾空格过滤
    v-slot:用于<template>,缩写#
    v-pre:跳过这个元素和其子元素的编译过程
    v-cloak:与CSS规则[v-cloak]{display:none}一起使用
    v-once:只渲染元素和组件一次。<span v-once>This will never change: {{msg}}</span>
    
    2. 实例的属性和方法
    • 属性
    常用:
    vm.$refs:返回Object,获取注册过ref特性的所有DOM元素和组件实例
    其他:
    vm.$data:Object,访问Vue实例的data属性
    vm.$props:Object,访问Vue实例的props属性
    vm.$el:Element,当前组件的根DOM元素
    vm.$options:Object,访问Vue的初始化选项
    vm.$parent:获取父实例
    vm.$root:当前组件树的根实例
    vm.$children
    vm.$slots:访问具名插槽的内容
    vm.$scopedSlots:访问作用域插槽的内容
    vm.$isServer
    vm.$attrs
    vm.$listeners
    
    • 方法
    常用:
    vm.$emit(eventName,[...args]):触发当前实例上的事件,常用于父子组件通信
    vm.$watch:观察 Vue 实例变化的一个表达式或计算属性函数
        vm.$watch('a.b.c', function (newVal, oldVal) {
          // 做点什么
        })
    vm.$set(target,key,value)
    其他:
    vm.$delete(target,key)
    vm.$on(event,callback):监听当前实例上的自定义事件
    vm.$once(event,callback):监听自定义事件,只触发一次,触发后自动移除监听器
    vm.$off([event,callback]):移除自定义事件
    vm.$mount([elementOrSelector]):可用于给vue实例手动挂载dom元素
    vm.$forceUpdate():迫使vue实例重新渲染
    vm.$nextTick([callback]):将回调延迟到下次DOM更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新
    vm.$destory():完全销毁一个实例。清理它与其它实例的连接,解绑它的全部指令及事件监听器
    
    3. 生命周期
    beforeCreate 实例初始化之后调用
    created 实例创建完成后被立即调用
    beforeMount 挂载开始之前被调用
    mounted 挂载到实例上去之后调用该钩子
    beforeUpdate 数据更新时调用,发生在虚拟 DOM 打补丁之前
    updated 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子
    activated keep-alive组件激活时调用
    deactivated keep-alive组件停用时调用
    beforeDestory 实例销毁之前调用
    destoryed 实例销毁后调用
    errorCaptured 当捕获一个来自子孙组件的错误时被调用
    
    4. 组件基础
    • 组件注册
    全局注册:
        Vue.component('name', {
            data () {
                return {
                    ...
                }
            },
            template: `<button>BTN</button>`
            ...
        })
    局部注册:
        var componentA = {}
        var componentB = {}
        var componentC = {}
        new Vue({
            el: '#app',
            components: {
                componentA,
                componentB
            }
        })
    
    5. 组件通信
    • 父子
    父给子传值:
        直接以属性的方式,如果是动态值可以用v-bind,子组件通过props接受值
    子给父传值:
        通过自定义事件。
        子组件通过$emit('faterEvent', ...params)触发父组件的自定义事件,父组件自定义事件触发一个自定义方法,其参数就是子组件传过来的值。
    
    • 兄弟
    可借助同一个父组件通信
    
    • 跨级
    vuex
    
    6. 插槽slot
    • 具名插槽
    定义:
    <slot name="header"></slot>
    调用:
    <template v-slot:header>
        <h1>Here might be a page title</h1>
    </template>
    
    • 作用域插槽
    让插槽内容能够访问子组件中才有的数据
    定义:
    <span>
      <slot v-bind:user="user">
        {{ user.lastName }}
      </slot>
    </span>
    调用:
    <current-user>
      <template v-slot:default="slotProps">
        {{ slotProps.user.firstName }}
      </template>
    </current-user>
    
    7. vue-router
    HTML:
        入口(声明式): <router-link to="/index"></router-link>
        出口: <router-view></router-view>
    JavaScript:
        import Vue from 'vue'
        import Router from 'vue-router'
        Vue.use(Router)
        // 定义路由
        const routes=[
            {path: '/index', component: ()=>require('../index')}
        ]
        // 创建router实例并配置路由
        const router = new Router({
            routes
        })
        // 根实例配置router
        const app = new Vue({
            router
        })
    
    可以在任何组件内通过this.$router访问路由器,通过this.$route访问当前路由。
    
    • 动态路由匹配
    eg: 将不同id的用户都指向User组件
        const router = new Router({
            routes: [
                // 动态路径参数,以冒号开头
                {path: '/user/:id', component: User}
            ]
        })
        
    多次路由如果渲染同个组件,组件会被复用,所以生命周期钩子不会再调用,可以使用watch监听$route对象。
    watch: {
        '$route': (to, from) {}
    }
    
    通配符(*):
        path: '*'
        path: 'user-*'
    如果使用通配符,$route.params会自动添加一个名为pathMatch参数
    // 给出一个路由 { path: '/user-*' }
    this.$router.push('/user-admin')
    this.$route.params.pathMatch // 'admin'
    // 给出一个路由 { path: '*' }
    this.$router.push('/non-existing')
    this.$route.params.pathMatch // '/non-existing'
    
    • 编程式导航
    Vue实例内部使用this.$router访问
    
    router.push(location, onComplete?, onAbort?)
    eg:
        // 字符串
        router.push('home')
        // 对象
        router.push({ path: 'home' })
        // 命名的路由,如果提供了path,params会被忽略
        router.push({ name: 'user', params: { userId: '123' }})
        // 带查询参数,变成 /register?plan=private
        router.push({ path: 'register', query: { plan: 'private' }})
    
    router.replace(location, onComplete?, onAbort?)
    
    router.go(n): 向前或后退多少步
    
    • 导航守卫
    全局前置守卫:
        const router = new Router({ ... })
        router.beforeEach((to, from, next) => {
            // 确保调用next方法,否则钩子不会被resolved
            // next() 进行下一个钩子
            // next(false) 中断当前的导航
            // next('/')或者next({path: '/'}) 中断当前导航,跳转到新导航
            // next(error) 终止导航,并触发router.onError()的回调
        })
    全局解析守卫:
        router.beforeResolve与上面的前置守卫类似
        区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用
    全局后置钩子:
        router.afterEach((to, from) => {})
    路由独享的守卫:
        const router = new Router({
            routes: [
                {
                    path: '/foo',
                    component: Foo,
                    beforeEnter: (to, from, next) => {}
                }
            ]
        })
    组件内的守卫:
        export default {
            name: 'Foo',
            beforeRouteEnter(to, from, next) {
                // 在渲染该组件的对应路由被 confirm 前调用
                // 不!能!获取组件实例 `this`
                // 因为当守卫执行前,组件实例还没被创建
                
                // 可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数
                next(vm => {
                    // 通过 `vm` 访问组件实例
                })
            },
            beforeRouteUpdate (to, from, next) {
                // 在当前路由改变,但是该组件被复用时调用
                // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
                // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
                // 可以访问组件实例 `this`
            },
            beforeRouteLeave (to, from, next) {
                // 导航离开该组件的对应路由时调用
                // 可以访问组件实例 `this`
            }
        }
    
    • 路由元信息
    meta: { requiresAuth: true }
    访问元信息:
        路由是可以嵌套的,因此一个路由匹配成功后,可能匹配多个路由记录
        $route.matched数组
        router.beforeEach((to, from, next) => {
          if (to.matched.some(record => record.meta.requiresAuth)) {
            if (!auth.loggedIn()) {
              next({
                path: '/login',
                query: { redirect: to.fullPath }
              })
            } else {
              next()
            }
          } else {
            next() // 确保一定要调用 next()
          }
        })
    
    • 页面滚动
    const router = new Router({
      routes: [...],
      scrollBehavior (to, from, savedPosition) {
        // return 期望滚动到哪个的位置
        return { x: 0, y: 0 }
      }
    })
    
    • 路由懒加载
    const Home = () => import('@/pages/home/Home')
    (resolve) => require(['pages/marketing-center/mission-medal/mission-rules/mission-rules'], resolve)
    
    8. vuex

    State、Getter、Mutation、Action、Module

    为什么要用vuex:
        当多个组件共享状态时(多个视图依赖同一状态,不同视图的行为需要变更同一状态)
    vuex和单纯的全局对象有两点不同:
        1.vuex的存储是响应式的,当vue组件从store中读取状态时,若store中的状态发生变化,那么相应的组件也会得到高效更新。
        2.不能直接改变store中的状态。改变状态的唯一途径就是显示提交mutation。
    const store = new Vuex.Store({
        state: {
            count: 0
        },
        mutation: {
            increment(state) {
                state.count++
            }
        }
    })
    const app = new Vue({
        el: '#app',
        store
    })
    this.$store.state.count
    this.$store.commit('increment')
    
    • mapState辅助函数
    import { mapState } from 'vuex'
    export default {
        computed: {
            ...mapState(['count'])
        }
    }
    
    • Getter
    就像计算属性一样,getter的返回值会根据它的依赖被缓存起来,且只有当依赖值发生了改变才会被重新计算。
    const store = new Vuex.Store({
      state: {
        todos: [
          { id: 1, text: '...', done: true },
          { id: 2, text: '...', done: false }
        ]
      },
      getters: {
        doneTodos: state => {
          return state.todos.filter(todo => todo.done)
        }
      }
    })
    通过属性访问:
        this.$store.getters.doneTodos
    通过方法访问:
        定义时返回一个函数:
            getters: {
                getTodoById: (state) => (id) => {
                    return state.todos.find(todo => todo.id === id)
                }
            }
        访问时可以传参数查询:
            this.$store.getters.getTodoById(2)
    
    • Mutation
    更改vuex的store中状态的唯一方法是提交mutation
    mutation必须是同步函数
    const store = new Vuex.Store({
        state: {
            count: 1
        },
        mutations: {
            increment (state) {
                state.count++
            }
        }
    })
    this.$store.commit('increment')
    或者
    methods: {
        ...mapMutations([
            // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
            'increment'
        ])
    }
    
    • Action
    Action类似于mutation,不同在于:
        Action提交的是mutation,而不是直接变更状态
        Action可以包含任意异步操作
    const store = new Vuex.Store({
        state: {
            count: 0
        },
        mutations: {
            increment (state) {
                state.count++
            }
        },
        actions: {
            increment (context) {
                // 可以异步操作
                setTimeout(() => {
                    context.commit('increment')
                }, 1000)
            }
        }
    })
    分发Action:
    this.$store.dispatch('increment')
    或者
    methods: {
        ...mapActions(['increment'])
    }
    
    • Module
    由于使用单一状态树,当应用变得复杂时,store对象会非常臃肿。
    因此,vuex允许我们将store分割成模块(module),每个模块拥有自己的state、mutation、action、getter、以及嵌套子模块。
    const moduleA = {
      state: { ... },
      mutations: { ... },
      actions: { ... },
      getters: { ... }
    }
    const moduleB = {
      state: { ... },
      mutations: { ... },
      actions: { ... }
    }
    const store = new Vuex.Store({
      modules: {
        a: moduleA,
        b: moduleB
      }
    })
    this.$store.state.a // -> moduleA 的状态
    this.$store.state.b // -> moduleB 的状态
    

    nodeJs

    • ECMAScript(语言基础,如:语法、数据类型结构以及一些内置对象)
    • os(操作系统)
    • file(文件系统)
    var fs = require('fs')
    fs.readFile('文件名', 'utf-8', function(err, data){})
    fs.readFileSync('文件名', 'utf-8')
    fs.writeFile('输出文件名', data, function(err){})
    fs.writeFile('输出文件名', data)
    fs.stat('文件名', function(err, stat){
        if (err) {
            
        } else {
            // 是否是文件:
            console.log('isFile: ' + stat.isFile());
            // 是否是目录:
            console.log('isDirectory: ' + stat.isDirectory());
            if (stat.isFile()) {
                // 文件大小:
                console.log('size: ' + stat.size);
                // 创建时间, Date对象:
                console.log('birth time: ' + stat.birthtime);
                // 修改时间, Date对象:
                console.log('modified time: ' + stat.mtime);
            }
        }
    })
    
    • stream
    var fs = require('fs')
    // 打开一个流
    var rs = fs.createReadStream('文件名', 'uft-8')
    rs.on('data', function(chunk){}) // data可能有多次,每次传递的chunk是流的一部分
    rs.on('end', function(){})
    rs.on('error', function(err){})
    
    // 用流写入文件
    var ws = fs.createWriteStream('输出文件名', 'utf-8')
    ws.write('文本数据。。。')
    ws.write(newBuffer('用流写二进制数据', 'utf-8')
    ws.end()
    
    // 用流复制
    var rs = fs.createReadStream('sample.txt');
    var ws = fs.createWriteStream('copied.txt');
    rs.pipe(ws);
    
    • http(网络系统)
    var http = require('http');
    // 创建http server,并传入回调函数:
    var server = http.createServer(function (request, response) {
        // 回调函数接收request和response对象,
        // 获得HTTP请求的method和url:
        console.log(request.method + ': ' + request.url);
        // 将HTTP响应200写入response, 同时设置Content-Type: text/html:
        response.writeHead(200, {'Content-Type': 'text/html'});
        // 将HTTP响应的HTML内容写入response:
        response.end('<h1>Hello world!</h1>');
    });
    // 让服务器监听8080端口:
    server.listen(8080);
    
    • web框架(koa2)
    对http有封装,使用Promise并配合async来实现异步。
    // 导入koa,和koa 1.x不同,在koa2中,我们导入的是一个class,因此用大写的Koa表示:
    const Koa = require('koa');
    // 创建一个Koa对象表示web app本身:
    const app = new Koa()
    // 对于任何请求,app将调用该异步函数处理请求:
    app.use(async (ctx, next) => {
        await next();
        ctx.response.type = 'text/html';
        ctx.response.body = '<h1>Hello, koa2!</h1>';
    });
    // 在端口3000监听:
    app.listen(3000);
    
    • 处理不同的URL(koa-router)
    const Koa = require('koa');
    // 注意require('koa-router')返回的是函数:
    const router = require('koa-router')();
    const app = new Koa();
    // log request URL:
    app.use(async (ctx, next) => {
        console.log(`Process ${ctx.request.method} ${ctx.request.url}...`);
        await next();
    });
    // add url-route:
    router.get('/hello/:name', async (ctx, next) => {
        var name = ctx.params.name;
        ctx.response.body = `<h1>Hello, ${name}!</h1>`;
    });
    router.get('/', async (ctx, next) => {
        ctx.response.body = '<h1>Index</h1>';
    });
    // add router middleware:
    app.use(router.routes());
    app.listen(3000);
    console.log('app started at port 3000...');
    
    • 处理post请求,获取body内容(koa-bodyparser)
    const Koa = require('koa');
    const app = new Koa();
    const bodyParser = require('koa-bodyparser');
    app.use(bodyParser());
    
    • database(数据库)
    //引入数据库
    var mysql=require('mysql');
    //实现本地链接
    var connection = mysql.createConnection({
        host: 'localhost',
        user: 'user',
        password: '123456',
        database: 'test'
    })
    connection.query('SELECT * FROM users WHERE id = ?', ['123'], function(err, rows) {});
    connection.query("INSERT INTO demo SET ?", post, function (error, results, fields) {})
    ...
    
    • ORM框架(Sequelize)
    const Sequelize = require('sequelize');
    // 连接数据库
    let sequelize = new Sequelize(config.database, config.username, config.password, {
      host: config.host,
      dialect: config.dialect,
      pool: config.pool
    });
    sequelize.define(tableName, attrs, {
        tableName,
        timestamps: false,
        freezeTableName: true,
        // 钩子函数,统一设置id、createdAt等这些基础字段的值
        hooks: {
          beforeValidate: function (obj) {
            let now = Date.now();
            if (obj.isNewRecord) {
              if (!obj.id) {
                obj.id = generateId();
              }
              obj.createdAt = now;
              obj.updatedAt = now;
              obj.version = 0;
              obj.isDelete = false;
            } else {
              obj.updatedAt = Date.now();
              obj.version++;
            }
          }
        }
    });
    

    相关文章

      网友评论

          本文标题:前端面试知识点整理(附答案)

          本文链接:https://www.haomeiwen.com/subject/ndfhcctx.html