2019前端最全面试题(三)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
.cn 域名,1个 12个月
云解析 DNS,旗舰版 1个月
简介: 2019前端最全面试题(三)

如何用css实现瀑布流布局

利用column-count和break-inside这两个CSS3属性即可,复制如下代码即可察看效果

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        body {
            margin: 0;
        }
        .waterfall-container {
            /*分几列*/
            column-count: 2;
            width: 100%;
            /* 列间距 */
            column-gap: 10px;
        }
        .waterfall-item {
            break-inside: avoid;
            width: 100%;
            height: 100px;
            margin-bottom: 10px;
            background: #ddd;
            column-gap: 0;
            text-align: center;
            color: #fff;
            font-size: 40px;
        }
    </style>
</head>
<body>
    <div class="waterfall-container">
        <div class="waterfall-item" style="height: 100px">1</div>
        <div class="waterfall-item" style="height: 300px">2</div>
        <div class="waterfall-item" style="height: 400px">3</div>
        <div class="waterfall-item" style="height: 100px">4</div>
        <div class="waterfall-item" style="height: 300px">5</div>
        <div class="waterfall-item" style="height: 600px">6</div>
        <div class="waterfall-item" style="height: 400px">7</div>
        <div class="waterfall-item" style="height: 300px">8</div>
        <div class="waterfall-item" style="height: 700px">9</div>
        <div class="waterfall-item" style="height: 100px">10</div>
    </div>
</body>
</html>

文本超出部分显示省略号

单行
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
多行
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3; // 最多显示几行
overflow: hidden;

利用伪元素画三角

.info-tab {
    position: relative;
}
.info-tab::after {
    content: '';
    border: 4px solid transparent;
    border-top-color: #2c8ac2;
    position: absolute;
    top: 0;
}


已知父级盒子的宽高,子级img宽高未知,想让img铺满父级盒子且图片不能变形

需要用到cssobject-fit属性

div {
    width: 200px;
    height: 200px;
}
img {
    object-fit: cover;
    width: 100%;
    height: 100%;
}
MDN

iframe的作用

iframe是用来在网页中插入第三方页面,早期的页面使用iframe主要是用于导航栏这种很多页面都相同的部分,这样在切换页面的时候避免重复下载。

优点

  1. 便于修改,模拟分离,像一些信息管理系统会用到。
  2. 但现在基本不推荐使用。除非特殊需要,一般不推荐使用。

缺点

  1. iframe的创建比一般的DOM元素慢了1-2个数量级
  2. iframe标签会阻塞页面的的加载,如果页面的onload事件不能及时触发,会让用户觉得网页加载很慢,用户体验不好,在Safari和Chrome中可以通过js动态设置iframe的src属性来避免阻塞。
  3. iframe对于SEO不友好,替换方案一般就是动态语言的Incude机制和ajax动态填充内容等。

css hack是什么

由于不同的浏览器,比如Internet Explorer 6,Internet Explorer 7,Mozilla Firefox等,对CSS的解析认识不一样,因此会导致生成的页面效果不一样,得不到我们所需要的页面效果。

这个时候我们就需要针对不同的浏览器去写不同的CSS,让它能够同时兼容不同的浏览器,能在不同的浏览器中也能得到我们想要的页面效果。

这个针对不同的浏览器写不同的CSS code的过程,就叫CSS hack,也叫写CSS hack。

具体请看:


http://www.cnblogs.com/Renyi-...

过渡与动画的区别是什么

  • transition

可以在一定的时间内实现元素的状态过渡为最终状态,用于模拟以一种过渡动画效果,但是功能有限,只能用于制作简单的动画效果而动画属性

  • animation

可以制作类似Flash动画,通过关键帧控制动画的每一步,控制更为精确,从而可以制作更为复杂的动画。

什么是外边距合并

外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距。

合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者。

去除inline-block元素间间距的方法

  • 移除空格
  • 使用margin负值
  • 使用font-size:0
  • letter-spacing
  • word-spacing

更详细的介绍请看:去除inline-block元素间间距的N种方法



JavaScript问题

同源策略

同源策略可防止 JavaScript 发起跨域请求。源被定义为 URI、主机名和端口号的组合。此策略可防止页面上的恶意脚本通过该页面的文档对象模型,访问另一个网页上的敏感数据。

跨域

  • 原因

浏览器的同源策略导致了跨域

  • 作用

用于隔离潜在恶意文件的重要安全机制

  • 解决
  1. jsonp ,允许 script 加载第三方资源
  2. 反向代理(nginx 服务内部配置 Access-Control-Allow-Origin *)
  3. cors 前后端协作设置请求头部,Access-Control-Allow-Origin 等头部信息
  4. iframe 嵌套通讯,postmessage

https://zhuanlan.zhihu.com/p/...


跨域资源共享 CORS 阮一峰

JSONP

这是我认为写得比较通俗易懂的一篇文章 直接转载过来


https://blog.csdn.net/hansexp...

域名收敛

PC 时代为了突破浏览器的域名并发限制。有了域名发散。


浏览器有并发限制,是为了防止DDOS攻击。


域名收敛:就是将静态资源放在一个域名下。减少DNS解析的开销。


域名发散:是将静态资源放在多个子域名下,就可以多线程下载,提高并行度,使客户端加载静态资源更加迅速。


域名发散是pc端为了利用浏览器的多线程并行下载能力。而域名收敛多用与移动端,提高性能,因为dns解析是是从后向前迭代解析,如果域名过多性能会下降,增加DNS的解析开销。

事件绑定的方式

  • 嵌入dom
<button onclick="func()">按钮</button>
  • 直接绑定
btn.onclick = function(){}
  • 事件监听
btn.addEventListener('click',function(){})

事件委托

事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。所有用到按钮的事件(多数鼠标事件和键盘事件)都适合采用事件委托技术,

使用事件委托可以节省内存。

 

<li>苹果li>
  <li>香蕉li>
  <li>凤梨li>
// good
document.querySelector('ul').onclick = (event) => {
  let target = event.target
  if (target.nodeName === 'LI') {
    console.log(target.innerHTML)
  }
}
// bad
document.querySelectorAll('li').forEach((e) => {
  e.onclick = function() {
    console.log(this.innerHTML)
  }
})

事件循环

事件循环是一个单线程循环,用于监视调用堆栈并检查是否有工作即将在任务队列中完成。如果调用堆栈为空并且任务队列中有回调函数,则将回调函数出队并推送到调用堆栈中执行。

事件模型

  • DOM0

直接绑定

<input onclick="sayHi()"/>
btn.onclick = function() {}
btn.onclick = null
  • DOM2

DOM2级事件可以冒泡和捕获

通过addEventListener绑定

通过removeEventListener解绑

// 绑定
btn.addEventListener('click', sayHi)
// 解绑
btn.removeEventListener('click', sayHi)
  • DOM3

DOM3具有更多事件类型

DOM3级事件在DOM2级事件的基础上添加了更多的事件类型,全部类型如下:

UI事件,当用户与页面上的元素交互时触发,如:load、scroll
焦点事件,当元素获得或失去焦点时触发,如:blur、focus
鼠标事件,当用户通过鼠标在页面执行操作时触发如:dbclick、mouseup
滚轮事件,当使用鼠标滚轮或类似设备时触发,如:mousewheel
文本事件,当在文档中输入文本时触发,如:textInput
键盘事件,当用户通过键盘在页面上执行操作时触发,如:keydown、keypress
合成事件,当为IME(输入法编辑器)输入字符时触发,如:compositionstart
变动事件,当底层DOM结构发生变化时触发,如:DOMsubtreeModified

https://www.jianshu.com/p/3ac...

如何自定义事件

  1. 原生提供了3个方法实现自定义事件
  2. createEvent,设置事件类型,是 html 事件还是 鼠标事件
  3. initEvent 初始化事件,事件名称,是否允许冒泡,是否阻止自定义事件
  4. dispatchEvent 触发事件

MDN

target和currentTarget区别

  • event.target

返回触发事件的元素

  • event.currentTarget

返回绑定事件的元素

prototype和__proto__的关系是什么

先说结论:

  1. prototype 用于访问函数的原型对象。
  2. __proto__ 用于访问对象实例的原型对象(或者使用 Object.getPrototypeOf())。
function Test() {}
const test = new Test()
test.__proto__ == Test.prototype // true

也就是说,函数拥有 prototype 属性,对象实例拥有 __proto__ 属性,它们都是用来访问原型对象的。

函数有点特别,它不仅是个函数,还是个对象。所以它也有 __proto__ 属性。

为什么会这样呢?因为函数是内置构造函数 Function 的实例:

const test = new Function('function Test(){}')
test.__proto__ == Function.prototype // true

所以函数能通过 __proto__ 访问它的原型对象。

由于 prototype 是一个对象,所以它也可以通过 __proto__ 访问它的原型对象。对象的原型对象,那自然是 Object.prototype 了。

function Test() {}
Test.prototype.__proto__ == Object.prototype // true

这样看起来好像有点复杂,我们可以换个角度来看。Object 其实也是内置构造函数:

const obj = new Object() // 我们可以把这个 obj 想象成原型对象 prototype
obj.__proto__ == Object.prototype // true  换个角度来看,相当于 prototype.__proto__ == Object.prototype

从这一点来看,是不是更好理解一点。

为了防止无休止的循环下去,所以 Object.prototype.__proto__ 是指向 null 的,null 是万物的终点。

Object.prototype.__proto__ == null // true

既然 null 是万物的终点,那使用 Object.create(null) 创建的对象是没有 __proto__ 属性的,也没有 prototype 属性。

原型继承

所有的 JS 对象(JS 函数是 prototype)都有一个 __proto__ 属性,指向它的原型对象。当试图访问一个对象的属性时,如果没有在该对象上找到,它还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。

继承

JS高程第3版 第6章 继承

寄生组合式继承

function SuperType(name) {
    this.name = name
    this.colors = ['red']
}
SuperType.prototype.sayName = function() {
    console.log(this.name)
}
// 继承实例属性
function SubType(name, age) {
    SuperType.call(this, name)
    this.age = age
}
function inheritPrototype(subType, superType) {
    let prototype = Object.create(superType.prototype)
    prototype.constructor = subType
    subType.prototype = prototype
}
// 继承原型方法
inheritPrototype(SubType, SuperType)
// 定义自己的原型方法
SubType.prototype.sayAge = function() {
    console.log(this.age)
}

闭包

闭包是指有权访问另一个函数作用域中的变量的函数。

function sayHi(name) {
    return () => {
       console.log(`Hi! ${name}`)
    }
}
const test = sayHi('xiaoming')
test() // Hi! xiaoming

虽然sayHi函数已经执行完毕,但是其活动对象也不会被销毁,因为test函数仍然引用着sayHi函数中的变量name,这就是闭包。


但也因为闭包引用着另一个函数的变量,导致另一个函数已经不使用了也无法销毁,所以闭包使用过多,会占用较多的内存,这也是一个副作用。

有一个函数,参数是一个函数,返回值也是一个函数,返回的函数功能和入参的函数相似,但这个函数只能执行3次,再次执行无效,如何实现

这个题目是考察闭包的使用

function sayHi() {
    console.log('hi')
}
function threeTimes(fn) {
    let times = 0
    return () => {
        if (times++ < 3) {
            fn()
        }
    }
}
const newFn = threeTimes(sayHi)
newFn()
newFn()
newFn()
newFn()
newFn() // 后面两次执行都无任何反应

通过闭包变量 times 来控制函数的执行

实现add函数,让add(a)(b)和add(a,b)两种调用结果相同

function add(a, b) {
    if (b === undefined) {
        return function(x) {
            return a + x
        }
    }
    return a + b
}

Ajax

Ajax(asynchronous JavaScript and XML)是使用客户端上的许多 Web 技术,创建异步 Web 应用的一种 Web 开发技术。借助 Ajax,Web 应用可以异步(在后台)向服务器发送数据和从服务器检索数据,而不会干扰现有页面的显示和行为。通过将数据交换层与表示层分离,Ajax 允许网页和扩展 Web 应用程序动态更改内容,而无需重新加载整个页面。实际上,现在通常将 JSON 替换为 XML,因为 JavaScript 对 JSON 有原生支持优势。


XMLHttpRequest API 经常用于异步通信。此外还有最近流行的fetch API。

let xmlhttp
if (window.XMLHttpRequest) {
    //  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
    xmlhttp = new XMLHttpRequest()
} else {
    // IE6, IE5 浏览器执行代码
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP")
}
xmlhttp.onreadystatechange = () => {
    if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
        document.getElementById("myDiv").innerHTML = xmlhttp.responseText
    }
}
xmlhttp.open("GET", "/ajax/test.txt", true)
xmlhttp.send()


目录
相关文章
|
编解码 前端开发 JavaScript
2019前端最全面试题(二)
2019前端最全面试题(二)
50 1
|
存储 缓存 JavaScript
2019前端最全面试题(六)
2019前端最全面试题(六)
57 0
|
数据采集 缓存 移动开发
2019前端最全面试题(四)
2019前端最全面试题(四)
81 0
|
5月前
|
存储 前端开发 JavaScript
最新Web前端经典面试试题及答案-史上最全前端面试题(含答案)
最新Web前端经典面试试题及答案-史上最全前端面试题(含答案)
|
5月前
|
XML 存储 前端开发
2022最新前端经典面试试题
2022最新前端经典面试试题
|
移动开发 JavaScript 前端开发
2019前端最全面试题(一)
2019前端最全面试题
62 1
|
网络协议 前端开发 JavaScript
2019前端最全面试题(五)
2019前端最全面试题(五)
57 0
|
19天前
|
SpringCloudAlibaba JavaScript 前端开发
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
分布式组件、nacos注册配置中心、openfegin远程调用、网关gateway、ES6脚本语言规范、vue、elementUI
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
|
2月前
|
存储 前端开发 JavaScript
前端语言串讲 | 青训营笔记
前端语言串讲 | 青训营笔记
29 0
|
4月前
|
JSON 前端开发 JavaScript
前端Ajax、Axios和Fetch的用法和区别笔记
前端Ajax、Axios和Fetch的用法和区别笔记
74 2
下一篇
无影云桌面