# 2020 / 3 / 17

自结题

# 1 / 写一个traverse函数,输出所有页面宽度和高度大于50像素的节点

function traverse(){
    var arr = []
    var elements = []

    if(document.all){
        elements = document.all
    }else{
        elements = document.getElementsByTagName('*')
    }

    for(var i = 0; i < elements.length; i++){
        var ele = elements[i]
        var width = parseFloat(ele.style.width) || ele.offsetWidth
        var height = parseFloat(ele.style.height) || ele.offsetWidth

        if(width > 50 && height > 50){
            arr.push(elements[i].tagName)
        }
    }

    return arr
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 2 / 请写一个表格以及对应的css,使表格奇数行为白色背景,偶数行为灰色背景,鼠标移上去时为黄色背景

<table class='table'>
    <tr><td>第一行</td></tr>
    <tr><td>第一行</td></tr>
    <tr><td>第一行</td></tr>
    <tr><td>第一行</td></tr>
</table>
1
2
3
4
5
6
.table tr:nth-child(odd){
    background-color:white;
}
.table tr:nth-child(even){
    background-color:gray;
}
.table tr:hover{
    background-color:yellow;
}
1
2
3
4
5
6
7
8
9

# 3 / 写一个求和的函数sum,达到下面的效果

# Demo

// Should equal 15
sum(1,2,3,4,5)
// Should equal 0
sum(5, null, -5)
// Should equal 9
sum('1.0', false, 1, true, 'A', 1, 'B', 1, 'C', 1, 'D', 1, 'E', 1, 'F', 1, 'G', 1)
// Should equal 0.3 not 0.30000000000004
sum(0.1, 0.2)
1
2
3
4
5
6
7
8
9
10

答案:

function sum(){
    var args = [].slice.call(arguments)
    return args.reduce((result, item) => {
        return result += parseFloat(item) || 0
    },0).toFixed(3) * 1000 / 1000
}
1
2
3
4
5
6

# 4 / 删除给定数组中的第二项和第三项,并且在新得到的新数组中第二项后面添加一个新值

var arr = ['a','b','c','d','e']
var newArr = arr.splice(1,2,'newValue')
1
2

# 5 / 请实现一个斐波那契(fibonacci)函数,要求其参数和返回值如下

#   @desc:fibonacci
#   @params:count{Number}
#   @return:result{Number}

第count个fibonacci值,计数从0开始
fibonacci数列为:[1,1,2,3,5,8,13,21,34,...]
1
2
3
4
5
6
function getNthFibonacci(count){
    if(count <= 1) return 1

    return getNthFibonacci(count-1) + getNthFibonacci(count-2)
}
1
2
3
4
5

# 5 / 填写内容让代码支持 a.name = 'name1'; b.name = 'name2'

function obj(name){
    if(name){
        this.name = name
    }
}
obj.prototype.name = 'name2'
var a = obj('name1')
var b = new obj
1
2
3
4
5
6
7
8

# 6 / 你了解Http状态码吗,请随便介绍一下

  • 100 Countinue 继续,一般在发送post请求时,已发送了http header之后服务器将返回此信息,表示确认,之后发送具体参数信息
  • 200 OK 正常返回信息
  • 201 Created 请求成功并且服务器创建了新的资源
  • 202 Accepted 服务器已接受请求,但尚未处理
  • 301 Moved Permanently 永久重定向请求的网页已永久移动到新位置
  • 302 Found 临时重定向
  • 303 See Other 临时重定向,且总是使用GET请求新的URI
  • 304 Not Modified 自从上次请求后,请求的网页未修改过
  • 400 Bad Request 服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求
  • 401 Unauthorized 请求未授权
  • 403 Forbidden 禁止访问
  • 404 Not Found 找不到与URI相匹配的资源
  • 500 Internal Server Error 最常见的服务器端错误
  • 503 Service Unavailable 服务器暂时无法处理请求(可能过载或维护)

# 7 / js 数组去重

Array.prototype.uniq = function(){
    // 长度为1,则直接返回当前的拷贝
    if(this.length <= 1) return this.slice(0)

    var result = []
    for(var i = 0; i < this.length; i++){
        // isExist判断是否已经存在,true存在,false不存在
        if(!isExist(result, this[i])){
            result.push(this[i])
        }
    }
    return result

    // 定义 isExist 函数
    function isExist(arr, item){
        if(arr.length === 0) return false

        var tmp

        for(var i = 0; i < arr.length; i++){
            tmp = arr[i]
            if(tmp === item){
                return true
            }

            // NaN 需要特殊处理
            if(!item && !tmp && tmp !== undefined && item !== undefined && isNaN(tmp) && isNaN(item)){
                return true
            }
        }

        return false
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 8 / 说说对网站重构的理解

网站重构:在不改变外部行为的前提下,简化结构,添加可读性,而在网站前端保持一致的行为。也就是说在不改变UI的情况下,对网站进行优化,在扩展的同时保持一致的UI

对于传统的网站来说重构是:

  • 表格布局改为 div + css
  • 使网站前端兼容于现代浏览器
  • 对于移动平台的优化
  • 针对于SEO进行优化
  • 深层次的网站重构应该考虑的方面
  • 减少代码间的耦合
  • 让代码保持弹性
  • 严格按规范编写代码
  • 设计可扩展的API
  • 代替旧有的框架,语言
  • 增强用户体验
  • 压缩Js,css,image等前端资源
  • 采用cdn来加速资源加载
  • 对于Js Dom操作优化

# 9 / Js对象的深度克隆代码实现

function cloneDeep(obj){
    var buf;
    if(obj instanceof Array){
        buf = []  // 创建一个空的数组
        var i = obj.length
        while(i--){
            buf[i] = cloneDeep(obj[i])
        }
        return buf
    }else if(obj instanceof Object){
        buf = {}
        for(var k in obj){
            buf[k] = cloneDeep(obj[k])
        }
        return buf
    }else{
        return obj
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 10 / Ajax是什么? Ajax的交互模型?同步和异步的区别?如何解决跨域问题?

Ajax全称异步的Javascript和XML,是一种创建快速动态的技术,通过在后台与服务器进行少量数据交互,实现网页的异步更新,在不更新加载整个界面的情况下,实现网页的局部更新

Ajax的交互模型(Ajax的过程)

  • 用户发出异步请求
  • 创建XMLHttpRequest对象
  • 可以设置Http请求的请求头
  • 设置响应状态改变的事件回调函数(onreadystatuschange)
  • 发送请求
  • 获取异步调用返回的数据
  • 使用Js和Dom进行局部解析

同步和异步的区别?

  • 同步:脚本会停留并等待服务器返回数据后再继续执行
  • 异步:脚本允许页面继续执行而不需等待服务器返回数据

跨域问题解决:

  • 使用document.domain + iframe
  • 使用window.name 利用同一页面下所有域名共享同一个name属性
  • 使用flash
  • 使用postMessage
  • 使用jsonP(创建动态script)

# 11 / 事件、Ie与火狐的事件机制有什么区别?如何阻止冒泡

  • 我们在网页中的某个操作(有的操作定义多个事件)。例如:点击一个按钮就会产生一个事件
  • 事件处理机制:
    • Ie是事件冒泡;firefox同时支持两种事件类型,即捕获型事件和冒泡型事件
  • 阻止事件冒泡
    • event.stopPropagation()
    • 旧版ie:event.cancelBubble = true

# 12 / web应用从服务器主动推送Data到客户端都有哪些方式?

  • html5 webSocket
  • webSocket 通过 flash
  • <script>标签的长时间连接
  • XHR长时间连接

# 13 / 写一个通用的事件侦听器函数

let eventListener = {
    // 页面加载完成后
    readyEvent:function(fn){
        if(fn == null){
            fn = document
        }
        var oldonload = window.onload
        if(typeof window.onload != 'function'){
            window.onload = fn
        }else{
            window.onload = function(){
                oldonload()
                fn()
            }
        }
    }

    // 绑定事件 ,参数:操作的元素,事件名称,事件处理函数
    addEvent:function(element, type, handler){
        if(element.addEventListener){
            // 参数:事件类型,事件处理函数,是否捕获
            element.addEventListener(type, handler, false)
        }else if(element.attachEvent){
            element.attachEvent('on'+type, function(){
                handler.call(element)
            })
        }else{
            element['on' + type] = handler
        }
    }


    // 移除事件
    removeEvent:function(element, type, handler){
        if(element.removeEventListener){
            element.removeEventListener(type, handler, false)
        }else if(element.detachEvent){
            element.detachEvent('on'+type, handler)
        }else{
            element['on' + type] = null
        }
    },

    // 阻止事件(主要是事件冒泡,因为Ie不支持事件捕获)
    stopPropagation:function(event){
        if(event.stopPropagation){
            event.stopPropagation()
        }else{
            event.cancelBubble = true
        }
    },

    // 取消事件的默认行为
    preventDefault:function(event){
        if(event.prevenrDefault){
            event.prevenrDefault()
        }else{
            event.returnValue = false
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

# 14 / eval作用是什么? 对它有什么建议?

  • 它的功能是把对应的字符串解析成Js代码并运行
  • 应该避免使用eval,不安全且非常耗性能

# 15 / 哪些地方会出现css阻塞,哪些地方会出现js阻塞?

Js的阻塞特性:所有浏览器在下载Js的时候,会阻止一切其他活动,比如其他资源的下载,内容的呈现等等。为了提高用户体验,新一代浏览器都支持并行下载Js,但是Js下载仍然会阻塞其他资源的下载(例如图片,css文件等)

由于浏览器为了防止出现Js修改Dom树,需要重新构建Dom树的情况,所以就会阻塞其他的下载和呈现

嵌入Js会阻塞所有内容的呈现,而外部Js只会阻塞其后内容的显示,2种方式都会阻塞其后资源的下载,也就是外部样式不会阻塞外部脚本的加载,但会阻塞外部脚本的执行

那Css怎么会阻塞加载?css本来是可以并行下载的,在什么情况下会出现阻塞加载?当Css后面跟着嵌入的Js时,该Css就会出现阻塞后面资源下载的情况,而当把嵌入的Js放到Css前面,就不会出现阻塞的情况了

根本原因:因为浏览器会维持Html中Css和Js的顺序,样式表必须在嵌入的Js执行先加载,解析完,而嵌入的Js会阻塞后面的资源加载,所以就会出现Css阻塞下载的情况

那么嵌入的Js应该放在那?

  • 放在底部,虽然放在底部照样会阻塞所有呈现
  • 如果嵌入Js放在head中,请把嵌入Js放在css头部
  • 使用 defer(延迟加载)
  • 不要在嵌入的Js中调用运行时间较长的函数,如果一定要用,可以用setTimeout来调用

# 16 / GET与POST区别? 何时使用POST?

  • GET:一般用于信息获取,使用URL来传递参数,对所发送信息的数量也有限制,一般在2000个字符
  • POST:一般用于修改服务器上的资源,对所发送的信息没有限制
  • GET方式需要使用 request.queryString 来取得变量的值
  • POST方式需要使用 request.from 来获取变量的值

即 GET 通过地址栏来传值,而 POST 通过提交表单来传值

在以下情况中,请使用 POST 请求:

  • 无法使用缓存文件(更新服务器上的文件或数据库)
  • 向服务器发送大量数据(POST没有数据量限制)
  • 发送包含位置字符的用户输入时,POST 比 GET 更稳定可靠