web笔试
类型判断用到哪些方法?
typeof和instanceof
值类型和引用类型的区别?
根据 JavaScript中的变量类型传递方式,又分为值类型和引用类型,在参数传递方式上,值类型是按值传递,引用类型是按共享传递。
说出下面代码的执行结果,并分析其原因?
function foo(a){
a = a * 10;
}
function bar(b){
b.value = 'new';
}
var a = 1;
var b = {value: 'old'};
foo(a);
bar(b);
console.log(a); // 1
console.log(b); // value: new
如何理解 JavaScript 的原型?
所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(null除外)
所有的引用类型(数组、对象、函数),都有一个__proto__属性,属性值是一个普通的对象
所有的函数,都有一个prototype属性,属性值也是一个普通的对象 所有的引用类型(数组、对象、函数),__proto__属性值指向它的构造函数的prototype属性值
// 要点一:自由扩展属性
var obj = {};obj.a = 100;
var arr = [];arr.a = 100;
function fn () {}
fn.a = 100;
//要点二:__proto__
console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fn.__proto__);
// 要点三:函数有 prototype
console.log(fn.prototype)
// 要点四:引用类型的 __proto__ 属性值指向它的构造函数的 prototype 属性值
console.log(obj.__proto__ === Object.prototype)
执行printName时很好理解,但是执行alertName时发生了什么?这里再记住一个重点 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__(即它的构造函数的prototype)中寻找,因此f.alertName就会找到Foo.prototype.alertName
JS中构造函数有普通函数有什么区别?
1.一般规则
构造函数都应该以 一个大写字母开头,eg:
function Person(){...}
而非构造函数则应该以一个小写字母开头,eg:
function person(){...}
2.调用方式
任何函数,只要通过 new 操作符来调用,那它就可以作为构造函数 ;
任何函数,如果不通过 new 操作符来调用,那它跟普通函数也没有什么两样。
prototype与__proto__区别?
如何理解 JS 的原型链?
当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__
(即它的构造函数的prototype
)中寻找。如果还是没有找到,继续往上找,这样一直往上找,你会发现是一个链式的结构,所以叫做“原型链”。如果一直找到最上层都没有找到,那么就宣告失败,返回undefined
。
最上层是什么 —— Object.prototype.__proto__= = null
变量提升?
把变量声明提升到当前执行环境的最顶端,先赋undefined(首先js引擎在读取js代码时会进行两个步骤,第一个步骤是解释,第二个步骤是执行。
所谓解释就是会先通篇扫描所有的Js代码,然后把所有声明提升到顶端,第二步是执行,执行就是操作一类的)
什么是执行上下文?
在一段 JS 脚本(即一个<script>标签中)执行之前,要先解析代码,解析的时候会先创建一个 全局执行上下文 环境,先把代码中即将执行的(内部函数的不算,因为你不知道函数何时执行)变量、函数声明都拿出来。变量先暂时赋值为undefined,函数则先声明好可使用。这一步做完了,然后再开始正式执行程序。再次强调,这是在代码执行之前才开始的工作。
另外,一个函数在执行之前,也会创建一个 函数执行上下文 环境,跟 全局上下文 差不多,不过 函数执行上下文 中会多出this
arguments
和函数的参数
总结一下:
- 范围:一段
<script>
、js 文件或者一个函数 - 全局上下文:变量定义,函数声明
- 函数上下文:变量定义,函数声明,
this
,arguments
题目:说出下面执行的结果(执行上下文,这里笔者直接注释输出了)
console.log(a) // undefined
var a = 100
fn('zhangsan') // 'zhangsan' 20
function fn(name) {
age = 20
console.log(name, age)
var age
}
console.log(b); // 这里报错
// Uncaught ReferenceError: b is not defined
b = 100;
为什么a是undefined,而b却报错了,实际 JS 在代码执行之前,要「全文解析」,发现var a,知道有个a的变量,存入了执行上下文,而b没有找到var关键字,这时候没有在执行上下文提前「占位」,所以代码执行的时候,提前报到的a是有记录的,只不过值暂时还没有赋值,即为undefined,而b在执行上下文没有找到,自然会报错(没有找到b的引用)。
请解释this的问题?
this
的值是在执行的时候才能确认,定义的时候不能确认! 为什么呢 —— 因为this
是执行上下文环境的一部分,而执行上下文需要在代码执行之前确定,而不是定义的时候。
var a = {
name: 'A',
fn: function () {
console.log(this.name)
}
}
a.fn() // this === a
a.fn.call({name: 'B'}) // this === {name: 'B'}
var fn1 = a.fn
fn1() // this === window
this执行会有不同,主要集中在这几个场景中
作为构造函数执行,
构造函数中 作为对象属性执行,上述代码中a.fn()
作为普通函数执行,上述代码中fn1()
用于call apply bind,上述代码中a.fn.call({name: 'B'})
题目:如何理解 JS 的作用域和作用域链?
JS 没有块级作用域,只有全局作用域和函数作用域,ES6才有块级作用域,全局作用域就是最外层的作用域,如果我们写了很多行 JS 代码,变量定义都没有用函数包括,那么它们就全部都在全局作用域中。这样的坏处就是很容易冲突。 jQuery、Zepto 等库的源码,所有的代码都会放在(function(){....})()中。因为放在里面的所有变量,都不会被外泄和暴露,不会污染到外面,不会对其他的库或者 JS 脚本造成影响。这是函数作用域的一个体现。
当前作用域没有定义的变量,这成为 自由变量 。自由变量如何得到 —— 向父级作用域寻找。如果父级也没呢?再一层一层向上寻找,直到找到全局作用域还是没找到,就宣布放弃。这种一层一层的关系,就是 作用域链 。自由变量将从作用域链中去寻找,但是依据的是函数定义时的作用域链,而不是函数执行时
闭包主要有哪些应用场景?
①函数作为返回值
②函数作为参数传递
闭包的优缺点?
1.保护函数内的变量安全,加强了封装性 ?
2.在内存中维持一个变量,若b为a的内部函数,闭包之所以会占用资源是当函数a执行结束后, 变量i不会因为函数a的结束而销毁, 因为b的执行需要依赖a中的变量。闭包的缺点就是常驻内存,会增大内存使用量,使用不当(例如用得太多)很容易造成内存泄露 ?
讲解下面代码的执行过程和结果?
var a = true;
setTimeout(function(){
a = false;
}, 100)
while(a){
console.log('while执行了')
}
因为JS是单线程的,所以进入while循环之后,没有「时间」(线程)去跑定时器了,所以这个代码跑起来是个死循环!
ES6 箭头函数中的this和普通函数中的有什么不同?
第一写起来更加简洁,第二 this是父作用域的 this
function fn() {
console.log('real', this) // {a: 100} ,该作用域下的 this 的真实的值
var arr = [1, 2, 3]
// 普通 JS
arr.map(function (item) {
console.log('js', this) // window 。普通函数,这里打印出来的是全局变量,令人费解
return item + 1
})
// 箭头函数
arr.map(item => {
console.log('es6', this) // {a: 100} 。箭头函数,这里打印的就是父作用域的 this
return item + 1
})
}
fn.call({a: 100})
ES6 模块化如何使用?
看笔记
设置文字居中?
横向:text-align:center
纵向:height等于line-height
ES6 class 和普通构造函数的区别
function MathHandle(x, y) {
this.x = x;
this.y = y;
}
MathHandle.prototype.add = function () {
return this.x + this.y;
};
var m = new MathHandle(1, 2);
console.log(m.add())
class MathHandle {
constructor(x, y) {
this.x = x;
this.y = y;
}
add() {
return this.x + this.y;
}
}
const m = new MathHandle(1, 2);
console.log(m.add())
JS 构造函数实现继承
// 动物
function Animal() {
this.eat = function () {
console.log('animal eat')
}
}
// 狗
function Dog() {
this.bark = function () {
console.log('dog bark')
}
}
Dog.prototype = new Animal()
// 哈士奇
var hashiqi = new Dog()
ES6 class 实现继承
class Animal {
constructor(name) {
this.name = name
}
eat() {
console.log(`${this.name} eat`)
}
}
class Dog extends Animal {
constructor(name) {
super(name)
this.name = name
}
say() {
console.log(`${this.name} say`)
}
}
const dog = new Dog('哈士奇')
dog.say()
dog.eat()
ES6 中新增的数据类型有哪些?
Set 和 Map
DOM 和 HTML 区别和联系?
HTML 是一个有既定标签标准的 XML 格式,标签的名字、层级关系和属性,都被标准化(否则浏览器无法解析),它也是一棵树。HTML 是一棵树,DOM 也是一棵树。可以认为 DOM 就是 JS 能识别的 HTML 结构,一个普通的 JS 对象或者数组。
property 和 attribute 的区别是什么?
两种有很大的区别,property 的获取和修改,是直接改变 JS 对象,而 attribute 是直接改变 HTML 的属性,attribute 就是对 HTML 属性的 get 和 set,和 DOM 节点的 JS 范畴的 property 没有关系。
什么是事件冒泡?
DOM 结构中,事件会沿着 DOM 树向上级节点冒泡,如果我们在上级节点中都绑定了事件,它是会根据 DOM 的结构来冒泡,从下到上挨个执行的。但是我们可以使用e.stopPropagation()来阻止冒泡
使用事件代理有何好处?
使用代理的优点如下:使代码简洁,减少浏览器的内存占用
HTTP 协议中,response 的状态码,常见的有哪些?
xhr.status即 HTTP 状态码,有 2xx 3xx 4xx 5xx 这几种,比较常用的有以下几种:
200 正常
3xx
301 永久重定向。如http://xxx.com这个 GET 请求(最后没有/),就会被301到http://xxx.com/(最后是/)
302 临时重定向。临时的,不是永久的
304 资源找到但是不符合请求条件,不会返回任何主体。如发送 GET 请求时,head 中有If-Modified-Since: xxx(要求返回更新时间是xxx时间之后的资源),如果此时服务器 端资源未更新,则会返回304,即不符合要求
404 找不到资源
5xx 服务器端出错了
另:
xhr.readyState是浏览器判断请求过程中各个阶段的,xhr.status是 HTTP 协议中规定的不同结果的返回状态说明。
xhr.readyState的状态码说明:
0 -代理被创建,但尚未调用 open() 方法。
1 -open() 方法已经被调用。
2 -send() 方法已经被调用,并且头部和状态已经可获得。
3 -下载中, responseText 属性已经包含部分数据。
4 -下载操作已完成
什么是跨域,如何实现跨域?前端处理跨域有没有遇到过,处理跨域的方式有哪几种方式去解决?
浏览器中有 同源策略,url 协议、域名、端口不同算跨域
解决跨域 - 服务器端设置 http header
1、JSONP
但是 HTML 中几个标签能逃避过同源策略——<script src="xxx">、<img src="xxxx"/>、<link href="xxxx">,这三个标签的src/href可以加载其他域的资源,不受同源策略限制。
2、服务器端设置 http header
response.setHeader("Access-Control-Allow-Origin", "http://m.juejin.com/"); // 第二个参数填写允许跨域的域名称,不建议直接写 "*"
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With");
response.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
// 接收跨域的cookie
response.setHeader("Access-Control-Allow-Credentials", "true");
cookie 和 localStorage 有何区别?
它是设计用来在服务器和客户端进行信息传递的,因此我们的每个 HTTP 请求都带着 cookie。但是 cookie 也具备浏览器端存储的能力(例如记住用户名和密码),因此就被开发者用上了。
使用方法:document.cookie = '···'
缺点:
存储量太小,只有 4KB
所有 HTTP 请求都带着,会影响获取资源的效率
API 简单,需要封装才能用
locationStorage 和 sessionStorage区别?
两者的区别就在于sessionStorage根据 session 过去时间而实现,而localStorage会永久有效。一些需要及时失效的重要信息放在sessionStorage中,一些不重要但是不经常设置的信息,放在localStorage中。
优点
存储量增大到 5MB
不会带到 HTTP 请求中
API 适用于数据存储 localStorage.setItem(key, value) localStorage.getItem(key)
说下你常用的几种布局方式?
盒模型、flex布局
谈谈你对flex布局的理解?
以下6个属性设置在容器上:
flex-direction属性决定主轴的方向
flex-wrap属性定义,如果一条轴线排不下,如何换行
justify-content属性定义了项目在主轴上的对齐方式。
align-items属性定义项目在交叉轴上如何对齐。
align-content属性定义了多根轴线的对齐方式
以下6个属性设置在项目上:
order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0
flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大
flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)
flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选
align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch
什么是盒子模型?
内边距、边框和外边距。它们三者就构成了一个“盒子”
盒子模型的宽度如何计算?
固定宽度的盒子:内容宽度(固定的宽度) + border宽度 + padding宽度 + margin宽度之和
充满父容器的盒子:内容宽度 + border宽度 + padding宽度 + margin宽度之和,内容宽度=父容器的内容宽度-(自己的 border宽度 + 自己的padding宽度 + 自己的margin宽度)
包裹内容的盒子:内容的宽度按照内容计算,盒子的宽度=内容宽度的基础上+padding宽度 + border宽度 + margin宽度之和。
为何 float 会导致父元素塌陷?
被设置了 float 的元素会脱离文档流,破坏了父标签的原本结构,使得父标签出现了坍塌现象
float 的重要的特性是什么?
包裹性和清空格
relative、absolute 和 fixed 有何区别?什么是定位上下文?
relative 会导致自身位置的相对变化,而不会影响其他元素的位置、大小,就是 relative 产生一个新的定位上下文。
absolute 元素脱离了文档结构,只要元素会脱离文档结构,它就会产生破坏性,导致父元素坍塌,absolute 元素具有“包裹性”。bsolute 元素具有“跟随性”。虽然 absolute 元素脱离了文档结构,若我们没有设置 top、left 的值,它的位置并不发生变化,呆在它原本的位置。absolute 元素会悬浮在页面上方,会遮挡住下方的页面内容。置了 top、left 值时,元素是相对于最近的定位上下文来定位的,而不是相对于浏览器定位。
fixed 和 absolute 是一样的,唯一的区别在于:absolute 元素是根据最近的定位上下文确定位置,而 fixed 根据 window (或者 iframe)确定位置。
relative 元素的定位永远是相对于元素自身位置的,和其他元素没关系,也不会影响其他元素。
absolute 设置了 top、left,浏览器会递归查找该元素的所有父元素,如果找到一个设置了position:relative/absolute/fixed的元素,就以该元素为基准定位,如果没找到,就以浏览器边界定位。
fixed 元素的定位是相对于 window (或 iframe)边界的,和其他元素没有关系。但是它具有破坏性,会导致其他元素位置的变化。
相对于flex布局,传统布局的方式是什么?
布局的传统解决方案基于盒子模型,依赖 display 属性 + position 属性 + float 属性
如何实现水平居中?
inline 元素用text-align: center;
block 元素可使用margin: auto;
绝对定位元素可结合left和margin实现,但是必须知道宽度
.container { //container是item的父级
position: relative;
width: 500px;
}
.item {
width: 300px;
height: 100px;
position: absolute;
left: 50%;
margin: -150px;
}
如何实现垂直居中?
inline 元素可设置line-height的值等于height值
绝对定位元素,可结合left和margin实现,但是必须知道尺寸(优点:兼容性好
缺点:需要提前知道尺寸)
.container {
position: relative;
height: 200px;
}
.item {
width: 80px;
height: 40px;
position: absolute;
left: 50%;
top: 50%;
margin-top: -20px;
margin-left: -40px;
}
绝对定位可结合transform实现居中(优点:不需要提前知道尺寸
缺点:兼容性不好)
.container {
position: relative;
height: 200px;
}
.item {
width: 80px;
height: 40px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background: blue;
}
绝对定位结合margin: auto(不需要提前知道尺寸,兼容性好)
测试:
<html>
<head>
<style>
.container {
position: relative;
height: 300px;
border:1px blue solid;
}
.item {
width: 100px;
height: 50px;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
background:red
}
</style>
<title>我的第一个 HTML 页面</title>
</head>
<body>
<div class="container"><div class="item"></div></div>
</body>
</html>
如何理解 HTML 语义化?
所谓“语义”就是为了更易读懂,分两部分:让人(写程序、读程序)更易读懂和让机器(浏览器、搜索引擎)更易读懂
为了加强 HTML 语义化,HTML5 标准中又增加了header section artical等标签。
CSS 的transition(过渡)和animation(动画)有何区别?一些常见的属性说下?
首先transition和animation都可以做动效,从语义上来理解,transition是过渡,由一个状态过渡到另一个状态,比如高度100px过渡到200px;而animation是动画,即更专业做动效的,animation有帧的概念,可以设置关键帧keyframe,一个动画可以由多个关键帧多个状态过渡组成,另外animation也包含多个属性。
transition: property duration timing-function delay
ransition-property :规定设置过渡效果的css属性名称
transition-duration :规定完成过渡效果需要多少秒或毫秒
transition-timing-function :指定过渡函数,规定速度效果的速度曲线
transition-delay :指定开始出现的延迟时间
animation: name duration timing-function delay iteration-count direction
animation-name 规定需要绑定到选择器的 keyframe 名称。。
animation-duration 规定完成动画所花费的时间,以秒或毫秒计。
animation-timing-function 规定动画的速度曲线。
animation-delay 规定在动画开始之前的延迟。
animation-iteration-count 规定动画应该播放的次数。
animation-direction 规定是否应该轮流反向播放动画。
动画相关
transform(变形)、translate(移动)
transform 属性向元素应用 2D 或 3D 转换。该属性允许我们对元素进行旋转、缩放、移动或倾斜。
translate() 方法转换画布的用户坐标系统,translate(dx, dy)
什么是重绘和回流?
重绘:指的是当页面中的元素不脱离文档流,而简单地进行样式的变化,比如修改颜色、背景等,浏览器重新绘制样式
回流:指的是处于文档流中 DOM 的尺寸大小、位置或者某些属性发生变化时,导致浏览器重新渲染部分或全部文档的情况
回流要比重绘消耗性能开支更大。
找出下面代码的优化点,并且优化它?
var data = ['string1', 'string2', 'string3'];
for(var i = 0; i < data.length; i++){
var dom = document.getElementById('list');
dom.innerHTML += '<li>' + data[i] + '</li>';
}
var dom = document.getElementById('list');
var data = ['string1', 'string2', 'string3'];
var frag = document.createDocumentFragment();
var li;
for(var i = 0; i < data.length; i++){
li = document.createElement("li");
li.innerHTML = data[i];
frag.appendChild(li); // 先放在 frag 中,最后一次性插入到 DOM 结构中。
}
listNode.appendChild(frag);
前端常见的安全问题有哪些?
XSS(跨站脚本攻击)和CSRF(跨站请求伪造)
何为构建工具,为什么要使用?
构建”也可理解为“编译”,就是将开发环境的代码转换成运行环境代码的过程。开发环境的代码是为了更好地阅读,而运行环境的代码是为了更快地执行,两者目的不一样,因此代码形式也不一样,为了达到这个目的,就要使用构建工具。
总结一下需要构建工具处理的几种情况:
构建工具的作用?
处理模块化、编译语法、代码压缩
何为抓包?
PC 端的网页,我们可以通过 Chrome、Firefox 等浏览器自带的开发者工具来查看网页的所有网络请求,以帮助排查 bug。这种监听、查看网络请求的操作称为抓包。
如何抓取数据?如何使用工具来配置代理?
监听请求:
Mac 系统下推荐使用 Charles,Windows 系统推荐使用 Fiddler
1、将安装好 Charles 的电脑和要抓包的手机,连接到同一个网络,保证 IP 段相同
2、手机设置网络代理,(代理IP)代理到电脑的 IP,代理的端口为8888,Charles选择“允许”代理
3、使用手机端访问的网页或者联网的请求,Charles 就能监听到
线上的地址代理到测试环境:
1、Charles 为例,点击菜单栏中 Tools 菜单,二级菜单中点击 Map Remote
2、选中 Enable Map Remote 复选框,然后点击 Add 按钮,添加一个代理项
3、将添加的代理项,map from 设置https://www.aaa.com/api/getuser?name=xxx,Map to设置http://168.1.1.100:8080/api/getuser?name=xxx
4、单击OK
谈谈Vue的生命周期的钩子?
beforeCreate (挂载目标(el)undefined,数据(data)undefined)
created(挂载目标(el)已被初始化 ,数据(data)已被初始化 )
beforeMount(挂载目标(el)已被初始化,数据(data)已被初始化) 模板的占位{{message}} 被替换
mounted(挂载目标(el)已被初始化,数据(data)已被初始化) 模板的占位{{message}} 被替换
首先会判断对象是否有el选项。如果有的话就继续向下编译,如果没有el选项,则停止编译,也就意味着停止了生命周期,直到在该vue实例上调用vm.$mount(el)
render函数选项 > template选项 > outer HTML
beforeUpdate(挂载目标(el)undefined,数据(data)undefined)
updated(挂载目标(el)undefined,数据(data)undefined)
beforeDestroy(挂载目标(el)undefined,数据(data)undefined)
destroyed(挂载目标(el)undefined,数据(data)undefined)
beforeDestroy钩子函数在实例销毁之前调用。在这一步,实例仍然完全可用。
destroyed钩子函数在Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
前端趋势?
简单一致(前端开发更加规范,统一),模块化,全栈
权限和Vue-Router的动态注册?
什么是restful?
要讲RESTful还得讲REST,REST是一种软件架构风格、设计风格,而不是标准,它规定了一些约束条件和原则,满足这些约束条件和原则的应用程序或(架构)设计就是 RESTful。
Vue改变数据的方式?
This和model
你以前的开发流程是怎样的?
多种开发方式结合使用,先确认大方向,根据需求用自顶向下,逐步求精方式,先定一个架构,再确定各模块。在各模块开发时,采用敏捷开发,迭代。通俗的说,是先打通业务逻辑,再扣细节。
React和Vue的对比?
Vue 数据驱动、组件化、轻量、简洁、高效、快速、模块友好,但是模板很容易出现运行时错误,难以测试,也不容易重构或分解。React Native是用JavaScript创建原生APP的库,如果你学习了React.js,那么你很快就可以学会React Native。开发人员可以构建一个web或者原生APP,他们不需要不同的知识体系和工具,但是学习成本较高,应用体积较大。
说一下你对原型与原型链的了解度,有几种方式可以实现继承,用原型实现继承有什么缺点,怎么解决?
原型链继承、构造继承、拷贝继承
缺点:要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中,无法实现多继承,来自原型对象的引用属性是所有实例共享的,创建子类实例时,无法向父类构造函数传参,解决用ES6的class
iframe的优缺点有哪些?
1.iframe能够原封不动的把嵌入的网页展现出来。
2.如果有多个网页引用iframe,那么你只需要修改iframe的内容,就可以实现调用的每一个页面内容的更改,方便快捷。
3.网页如果为了统一风格,头部和版本都是一样的,就可以写成一个页面,用iframe来嵌套,可以增加代码的可重用。
4.如果遇到加载缓慢的第三方内容如图标和广告,这些问题可以由iframe来解决。
5.重载页面时不需要重载整个页面,只需要重载页面中的一个框架页(减少了数据的传输,增加了网页下载速度)
6.方便制作导航栏,航栏在页面位置固定不变
①iframe会阻塞主页面的Onload事件;
② 搜索引擎的检索程序无法解读这种页面,不利于SEO;
③ 会影响页面的并行加载(并行加载:同一时间针对同一域名下的请求。一般情况,iframe和所在页面在同一个域下面,而浏览器的并加载的数量是有限制的)。
解决方案:
<iframe id="fram"></iframe>
document.getelementbyid("fram").src="a2.html"
为什么会有同源策略?
防止XSS
从发送一个url地址到返回页面,中间发生了什么?
1、首先,在浏览器地址栏中输入url
2、浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。若没有,则跳到第三步操作。
3、在发送http请求前,需要域名解析(DNS解析),解析获取相应的IP地址。
4、浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手。
5、握手成功后,浏览器向服务器发送http请求,请求数据包。
6、服务器处理收到的请求,将数据返回至浏览器
7、浏览器收到HTTP响应
8、读取页面内容,浏览器渲染,解析html源码
9、生成Dom树、解析css样式、js交互
10、客户端和服务器交互
11、ajax查询
说下工作中你做过的一些性能优化处理?
减少页面体积,提升网络加载:
静态资源的压缩合并(JS 代码压缩合并、CSS 代码压缩合并、雪碧图)
静态资源缓存(资源名称加 MD5 戳)
使用 CDN 让资源加载更快
优化页面渲染:
CSS 放前面,JS 放后面
懒加载(图片懒加载、下拉加载更多)
减少DOM 查询,对 DOM 查询做缓存
减少DOM 操作,多个操作尽量合并在一起执行(DocumentFragment)
事件节流
尽早执行操作(DOMContentLoaded)
使用 SSR 后端渲染,数据直接输出到 HTML 中,减少浏览器使用 JS 模板渲染页面 HTML 的时间
箭头函数有什么特性,其this指向谁?
特性:
1.对 this 的关联。函数内置 this 的值,取决于箭头函数在哪儿定义,而非箭头函数执行的上下文环境。
2.new 不可用。箭头函数不能使用 new 关键字来实例化对象,不然会报错。
3.this 不可变。函数内置 this 不可变,在函数体内整个执行环境中为常量。
4.没有arguments对象。更不能通过arguments对象访问传入参数。只能使用显式命名或其他ES6新特性来完成。
This:
箭头函数没有自己的this, 它的this是继承而来; 默认指向在定义它时所处的对象(宿主对象),而不是执行时的对象, 定义它的时候,可能环境是window; 箭头函数可以方便地让我们在 setTimeout ,setInterval中方便的使用this
如何实现一个promise,promise的原理,以及它的两个参数是什么?
const promise
=new
Promise(function(
resolve
,reject
){
// ... some code
if
(/* 异步操作成功 */){
resolve(
value
);
}
else
{
reject(
error
);
}
});
promise
.then(function(value
){
// success
},function(
error
){
// failure
});
也就是说promise对象代表了一个异步操作,可以将异步对象和回调函数脱离开来,通过then方法在这个异步操作上面绑定回调函数,使用catch方法捕获异常
promise中第二个参数的reject中执行的方法和promise.catch()都是失败执行的,分别这么写有什么区别,什么情况下会两个都同时用到?
reject中执行的方法仅能处理调用reject()时的异常,而catch同时处理声明Promise里的函数和then里的异常
举例:
auto.getData().then(function (results) {
res.send(results);
}, next);
这种写法,next函数只会处理getData中的reject时的异常情况。
auto.getData().then(function (results) {
res.send(results);
}).catch(next);
这种写法,catch会捕捉到在它之前的promise链上的代码抛出的异常,不仅getData,还包括then()里面。
map和set有没有用过,map数据结构有什么优点?
set成员的值都是唯一的,可用for of遍历
map各种类型的值(包括对象)都可以当作键,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果需要“键值对”的数据结构,Map 比 Object 更合适。
http、https、以及websocket的区别?
https协议需要到ca申请证书,一般免费证书很少,需要交费。http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议http和https使用的是完全不同的连接方式用的端口也不一样,前者是80,后者是443。http的连接很简单,是无状态的HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全。
WebSocket他是为了解决客户端发起多个http请求到服务器资源浏览器必须要经过长时间的轮询问题而生的,他实现了多路复用,他是全双工通信。在webSocket协议下客服端和浏览器可以同时发送信息。
Websocket与HTTP比较:
相同点:
1.都是基于TCP的应用层协议。
2.都使用Request/Response模型进行连接的建立。
3.在连接的建立过程中对错误的处理方式相同,在这个阶段WS可能返回和HTTP相同的返回码。
4.可以在网络中传输数据。
不同点:
1.WS使用HTTP来建立连接,但是定义了一系列新的header域,这些域在HTTP中并不会使用。
2.WS的连接不能通过中间人来转发,它必须是一个直接连接。
3.WS连接建立之后,通信双方都可以在任何时刻向另一方发送数据。
4.WS 连接建立之后,数据的传输使用帧来传递,不再需要Request消息。
5.WS的数据帧有序。
协商缓存和强缓存的区别?
说下计算机网络的相关协议?
TCP/IP协议
H5新特性?
新增选择器 document.querySelector、document.querySelectorAll
拖拽释放(Drag and drop) API
媒体播放的 video 和 audio
本地存储 localStorage 和 sessionStorage
离线应用 manifest
桌面通知 Notifications
语意化标签 article、footer、header、nav、section
增强表单控件 calendar、date、time、email、url、search
地理位置 Geolocation
多任务 webworker
全双工通信协议 websocket
历史管理 history
跨域资源共享(CORS) Access-Control-Allow-Origin
页面可见性改变事件 visibilitychange
跨窗口通信 PostMessage
Form Data 对象
绘画 canvas
DOM的操作:读,移动,移除,复制,创建
(1)创建新节点
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
(2)添加、移除、替换、插入
appendChild()
removeChild()
replaceChild()
insertBefore() //在已有的子节点前插入一个新的子节点
(3)查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的)
getElementById() //通过元素Id,唯一性
自动化,代码压缩工具?
UglifyJS
有什么样的MVC、MVVM前端框架?
bootstrap、Angular、React、Vue
小程序原理?
1. 提供了JavsScript运行环境,由JavaScript编写的业务代码完成逻辑层的处理2. 通过数据传输接口(注册Page时的data属性及后续的setData方法调用)将逻辑层的数据传输给视图层3. 视图层由WXML语言编写的模板通过“数据绑定”与逻辑层传输过来的数据merge成展现结果并展现4. 视图的样式控制由WXSS语言编写的样式规则进行配置
小程序异步?
wx.request({
url: 'test.php', //仅为示例,并非真实的接口地址
data: {
x: '' ,
y: ''
},
header: {
'content-type': 'application/json' // 默认值
},
success: function(res) {
console.log(res.data)
}
})
小程序如何提升应用速度?
小程序双向绑定和Vue区别?
如何实现一个自定义组件,不同组件之间如何通信的?
Vue父子组件如何通信的?
父组件向子组件,用props选项,子组件向父组件传递用事件
Vue的响应式原理你知道是怎么实现的吗?
新窗口打开网页,用到以下哪个值
_blank -- 在新窗口中打开链接
_parent -- 在父窗体中打开链接
_self -- 在当前窗体打开链接,此为默认值
_top -- 在当前窗体打开链接,并替换当前的整个窗体(框架页)
一个对应的框架页的名称 -- 在对应框架页中打开
谈谈document.ready和window.onload的区别
在Jquery里面,我们可以看到两种写法:$(function(){}) 和$(document).ready(function(){}),这两个方法的效果都是一样的,都是在dom文档树加载完之后执行一个函数(注意,不是全部文件加载完),而window.onload是在dom文档树加载完和所有文件加载完之后执行一个函数。也就是说$(document).ready要比window.onload先执行。
Doctype和严格模式与混杂模式的描述?
如果你的页面添加了<!DOCTYPE html>那么,那么就等同于开启了标准模式,那么浏览器就得老老实实的按照W3C的标准解析渲染页面,这样一来,你的页面在所有的浏览器里显示的就都是一个样子了
请写出下面的代码执行结果:
var str = 'google';
var reg = /o/g;
console.log(reg.test(str))
console.log(reg.test(str))
console.log(reg.test(str))
最后一个不是为true,而是false,这是因为reg这个正则有个g,即global全局的属性,这种情况下lastIndex就发挥作用了,因为有标志g,所以每次匹配都从上一次匹配文本之后的第一个字符的位置开始,因此第三个是false,解决方法如下:
(function(){
const reg = /o/g;
function isHasO(str){
// reg.lastIndex = 0; 这样就可以避免这种情况
return reg.test(str)
}
var str = 'google';
console.log(isHasO(str))
console.log(isHasO(str))
console.log(isHasO(str))
}())
让你写后端,你能写吗?
前后端通吃的就说没问题,懂一点或不懂的就说写过,若被安排到写后端,基本的例如接口,基本的业务逻辑,缓存、基本增删改查等没问题,较复杂的可以做到边学边开发。
xx平台是你独立开发的吗?
如何实现:左侧自适应,右侧固定宽度?
小程序会吗?
如果你有web前端基础,小程序实现一般应用根本不难。若没相关的经验,那就先了解结构,写个Hello World。面试时你就直接说做过简单的Demo,实际经验不多但是可以边学习边开发,一般当做拓展技能时他不会再问你更多的问题,若是专门应聘小程序岗位,你需要了解得更深,这个就不用多说了。
如:
写过简单的Demo,了解它的框架,它类似MVVM,自定义的标签语言WXML,样式WXSS,JavaScript原生实现业务逻辑。
一段文字,第一行居中,第二行居左,如何实现?
用嵌套解决
<!-- 只有一行时居中显示文字,多行居左显示,最多两行超过用省略号结尾 --> <div class="container"> <h2><p><em>我是单行标题居中</em></p></h2> <h2><p><em>我是两行标题两行标题两行标题居左</em></p></h2> <h2><p><em>我是超过两行的标题最后点号省略我是超过两行的标题最后点号省略我是超过两行的标题最后点号省略省略省略</em></p></h2> </div>
*{ margin:0; padding:0; } h2 em { position: relative; font-style: normal; text-align: left; overflow : hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } .container{ width:320px; padding:0 10px; margin:10px auto; background: #ddd; } .container p { display: inline-block; text-align: center; } h2{ text-align: center; padding:10px 0; }
计算出item元素的宽度,padding的值
.box{
font-size:14px;
}
.item{
font-size:16px;
width:1em;
padding-top:2em
}
有3个元素,分别设置他们的font-size为0、 6 、12,在Chrome浏览器看到的字体实际的size为?
谷歌下 css设置字体大小为12px及以下时,显示都是一样大小,都是默认12px;
请计算item元素的padding、margin值
.box{
width:100px
}
.item{
width:80px;
height:80px;
padding-top:20%;
margin-top:20%
}
<div class="box"><div class="item"></div></div>
请解释什么是闭包?
请解释什么叫做原型链,实现继承有哪些方法?
请解释call、apply的作用,他们之间有什么区别?
什么是XSS、CSRF,如何防止?
请使用JS实现斐波那契数列?
请解释var let const的区别?
请解释以下代码的最终输出结果?请使用ES6解决?(不能使用闭包)
const arr=[10,22,3,41]
for(var i=0;i<arr.length;i++){
setTimeout(()=>{
console.log('index:'+i+',elemnt:'+arr[i])
},3000)
}
setTimeout是个异步定时函数,js是单线程,所以就算延时为0,它也是要等到for循环执行完了,才到它执行,每执行一次for语句就会就会产生一个异步执行,放在等待队列里,所以最后执行时就是输出4个:
index:4,elemnt:undefined
传统方法:闭包
不太可行
采用立即执行函数
const arr=[10,22,3,41]
for(var i=0;i<arr.length;i++){
console.log('index:'+i+',elemnt:'+arr[i])
},3000)
}
const arr=[10,22,3,41]
for(let i=0;i<arr.length;i++){
setTimeout(()=>{
console.log('index:'+i+',elemnt:'+arr[i])
},3000)
}
let 为代码块的作用域,所以每一次 for 循环,console.log(i); 都引用到 for 代码块作用域下的i,因为这样被引用,所以 for 循环结束后,这些作用域在 setTimeout 未执行前都不会被释放。
下面是var带来的不合理场景
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
var arr = []; for (var i = 0; i < 10; i++) { arr[i] = function () { console.log(i); } } arr[5]() //10,a[5]输出f(){console.log(i);},后面加个括号代表执行f()
在上述代码中,变量i是var声明的,在全局范围类都有效,所以用来计数的循环变量泄露为全局变量。所以每一次循环,新的i值都会覆盖旧值,导致最后输出都是10。
而如果对循环使用let语句的情况,那么每次迭代都是为x创建新的绑定代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
var arr = []; for (let i = 0; i < 10; i++) { arr[i] = function () { console.log(i); } } arr[5]() //5,a[5]输出f(){console.log(i);},后面加个括号代表执行f()
【拓展】
当然,除了这种方式让数组找中的各个元素分别是不同的函数,我们还可以采用ES5中的闭包和立即函数两种方法。
1、采用闭包
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
function showNum(i) { return function () { console.log(i) } } var a = [] for (var i = 0; i < 5; i++) { a[i] = showNum(i)(); //循环输出1,2,3,4 }
2、采用立即执行函数
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
var a = [] for (var i = 0; i < 5; i++) { a[i] = (function (i) { return function () { console.log(i) } })(i) } a[2](); //2
把以下代码使用两种方法,依次输出0-9
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
var funcs = [] for (var i = 0; i < 10; i++) { funcs.push(function () { console.log(i) }) } funcs.forEach(function (func) { func(); //输出十个10 })
var funcs = [] for (var i = 0; i < 10; i++) { funcs.push(function () { console.log(i) }) } funcs.forEach(function (func) { func(); //输出十个10 })
方法一:使用立即执行函数
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
var funcs = [] for (var i = 0; i < 10; i++) { funcs.push((function (value) { return function () { console.log(value) } }(i))) } funcs.forEach(function (func) { func(); //依次输出0-9 })
var funcs = [] for (var i = 0; i < 10; i++) { funcs.push((function (value) { return function () { console.log(value) } }(i))) } funcs.forEach(function (func) { func(); //依次输出0-9 })
方法二:使用闭包
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
function show(i) { return function () { console.log(i) } } var funcs = [] for (var i = 0; i < 10; i++) { funcs.push(show(i)) } funcs.forEach(function (func) { func(); //0 1 2 3 4 5 6 7 8 9 })
function show(i) { return function () { console.log(i) } } var funcs = [] for (var i = 0; i < 10; i++) { funcs.push(show(i)) } funcs.forEach(function (func) { func(); //0 1 2 3 4 5 6 7 8 9 })
方法三:使用let
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
var funcs = [] for (let i = 0; i < 10; i++) { funcs.push(function () { console.log(i) }) } funcs.forEach(function (func) { func(); //依次输出0-9 })
var funcs = [] for (let i = 0; i < 10; i++) { funcs.push(function () { console.log(i) }) } funcs.forEach(function (func) { func(); //依次输出0-9 })
其他知识点:forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。
setTimeout(function () { console.log(1) }, 0); new Promise(function executor(resolve) { console.log(2); for (var i = 0; i < 10000; i++) { i == 9999 && resolve(); } console.log(3); }).then(function () { console.log(4); }); console.log(5);
首先,先碰到一个 setTimeout,于是会先设置一个定时,在定时结束后将传递这个函数放到任务队列里面,因此开始肯定不会输出 1 。
然后,是一个 Promise,里面的函数是直接执行的,因此应该直接输出 2 3 。 然后,then
方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行(Promise 构造函数是同步执行的,promise.then 中的函数是异步执行的)。 因此,应当先输出 5,然后再输出 4 , 最后在到下一个 tick,就是 1 。
分析下列程序代码,得出运行结果,解释其原因?
Promise.resolve(1) .then((res) => { console.log(res) return 2 }) .catch((err) => { return 3 }) .then((res) => { console.log(res) })
运行结果: 1 2 原因: promise 可以链式调用。提起链式调用我们通常会想到通过 return this 实现,不过 Promise 并不是这样实现的。promise 每次调用 .then 或者 .catch 都会返回一个新的 promise,从而实现了链式调用。
const promise = new Promise((resolve, reject) => { setTimeout(() => { console.log('once') resolve('success') }, 1000) }) const start = Date.now() promise.then((res) => { console.log(res, Date.now() - start) }) promise.then((res) => { console.log(res, Date.now() - start) })
运行结果: once success 1001 success 1001 原因: promise 的 .then 或者 .catch 可以被调用多次,但这里 Promise 构造函数只执行一次。或者说 promise 内部状态一经改变,并且有了一个值,那么后续每次调用 .then 或者 .catch 都会直接拿到该值。
参考:https://www.cnblogs.com/fengxiongZz/p/8191503.html
请使用正则验证小于2000的数字?
let re=/^([1-9]{0,3}|(1)\d{3}|2000)$/g
给定两个数,求这两个数的和,不可以直接使用这两个相加?
//方法1
function add() { if (arguments.length === 1) { return arguments[0]; } else { for (var i = 0, result = 0; i < arguments.length; i++) { result += arguments[i]; } return result } } console.log(add(1,1,1))
//方法2 function sum() { var x = 0; for (var i = 0; i < arguments.length; ++i) { x += arguments[i]; } return x; } console.log(sum(1,1,2))
请说明你的代码是如何命名JS、CSS的?
BEM
get的缺点?post的缺点?两者区别
get安全性低(所发送的数据是 URL 的一部分,数据会被缓存)
传送数据量小(数据量限制,各浏览器不同,其中Chrome最大长度8182byte)
(http协议并未规定get和post的长度限制 ,get的最大长度限制是因为浏览器和web服务器限制了URL的长度 )
(1)post更安全(不会作为url的一部分,不会被缓存、保存在服务器日志、以及浏览器浏览记录中)
(2)post发送的数据更大(get有url长度限制)
(3)post能发送更多的数据类型(get只能发送ASCII字符)
(4)post比get慢 (缺点)
(5)post用于修改和写入数据,get一般用于搜索排序和筛选之类的操作(淘宝,支付宝的搜索查询都是get提交),目的是资源的获取,读取数据
更多,见:
http://www.w3school.com.cn/tags/html_ref_httpmethods.asp
如果你和你团队成员CSS命名有冲突,怎么解决?
请自己实现一个promise?
ES6
var fn=function(resolve, reject){ console.log('begin to execute!'); var number=Math.random(); if(number<=0.5){ resolve('less than 0.5'); }else{ reject('greater than 0.5'); } } var p=new Promise(fn); p.then(function(data){ console.log('resolve: ', data); }, function(data){ console.log('reject: ', data); })
六、分析下列程序代码,得出运行结果,解释其原因
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
Promise.resolve() .then(() => { return new Error('error!!!') }) .then((res) => { console.log('then: ', res) }) .catch((err) => { console.log('catch: ', err) })
Promise.resolve() .then(() => { return new Error('error!!!') }) .then((res) => { console.log('then: ', res) }) .catch((err) => { console.log('catch: ', err) })
运行结果及原因
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
运行结果 then: Error: error!!! at Promise.resolve.then (...) at ... 原因 .then 或者 .catch 中 return 一个 error 对象并不会抛出错误,所以不会被后续的 .catch 捕获,需要改成其中一种: return Promise.reject(new Error('error!!!')) throw new Error('error!!!') 因为返回任意一个非 promise 的值都会被包裹成 promise 对象,即 return new Error('error!!!') 等价于 return Promise.resolve(new Error('error!!!'))。
运行结果 then: Error: error!!! at Promise.resolve.then (...) at ... 原因 .then 或者 .catch 中 return 一个 error 对象并不会抛出错误,所以不会被后续的 .catch 捕获,需要改成其中一种: return Promise.reject(new Error('error!!!')) throw new Error('error!!!') 因为返回任意一个非 promise 的值都会被包裹成 promise 对象,即 return new Error('error!!!') 等价于 return Promise.resolve(new Error('error!!!'))。
七、分析下列程序代码,得出运行结果,解释其原因
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
const promise = Promise.resolve() .then(() => { return promise }) promise.catch(console.error)
const promise = Promise.resolve() .then(() => { return promise }) promise.catch(console.error)
运行结果及原因
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
运行结果 TypeError: Chaining cycle detected for promise #<Promise> at <anonymous> at process._tickCallback (internal/process/next_tick.js:188:7) at Function.Module.runMain (module.js:667:11) at startup (bootstrap_node.js:187:16) at bootstrap_node.js:607:3 原因 .then 或 .catch 返回的值不能是 promise 本身,否则会造成死循环。
运行结果 TypeError: Chaining cycle detected for promise #<Promise> at <anonymous> at process._tickCallback (internal/process/next_tick.js:188:7) at Function.Module.runMain (module.js:667:11) at startup (bootstrap_node.js:187:16) at bootstrap_node.js:607:3 原因 .then 或 .catch 返回的值不能是 promise 本身,否则会造成死循环。
八、分析下列程序代码,得出运行结果,解释其原因
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
Promise.resolve(1) .then(2) .then(Promise.resolve(3)) .then(console.log)
Promise.resolve(1) .then(2) .then(Promise.resolve(3)) .then(console.log)
运行结果及原因
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
运行结果 1 原因 .then 或者 .catch 的参数期望是函数,传入非函数则会发生值穿透。
运行结果 1 原因 .then 或者 .catch 的参数期望是函数,传入非函数则会发生值穿透。
九、分析下列程序代码,得出运行结果,解释其原因
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
Promise.resolve() .then(function success (res) { throw new Error('error') }, function fail1 (e) { console.error('fail1: ', e) }) .catch(function fail2 (e) { console.error('fail2: ', e) })
Promise.resolve() .then(function success (res) { throw new Error('error') }, function fail1 (e) { console.error('fail1: ', e) }) .catch(function fail2 (e) { console.error('fail2: ', e) })
运行结果及原因
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
运行结果 fail2: Error: error at success (...) at ... 原因 .then 可以接收两个参数,第一个是处理成功的函数,第二个是处理错误的函数。.catch 是 .then 第二个参数的简便写法,但是它们用法上有一点需要注意:.then 的第二个处理错误的函数捕获不了第一个处理成功的函数抛出的错误,而后续的 .catch 可以捕获之前的错误。
运行结果 fail2: Error: error at success (...) at ... 原因 .then 可以接收两个参数,第一个是处理成功的函数,第二个是处理错误的函数。.catch 是 .then 第二个参数的简便写法,但是它们用法上有一点需要注意:.then 的第二个处理错误的函数捕获不了第一个处理成功的函数抛出的错误,而后续的 .catch 可以捕获之前的错误。
ES5
https://www.cnblogs.com/malingyang/p/6535805.html
有了解Vue数据绑定的原理吗?
这道题,面试官能够当着你面写出来的,没几个。他们只是知道原理而已,原理涉及 观察者模式,我当时回答这个答案时,面试官会抓着问我,观察者模式是什么?会被连着问出来很多东西,若你不是应聘高级开发或CTO,那么Vue原理或拆Vue的轮子,你可以说最近正在学习这方面的知识,毕竟初级开发,会用就够了。
了解touch事件吗?
-
click事件的300ms延迟问题。
2007年第一代iphone发布,由于那个年代所有的网页都是针对大屏的pc端设计的,iphone的Safari浏览器为了让用户浏览网页的时候可以浏览到整个网页,把viewport设置为960px(参考前面的文章),好是好,但是由于缩放了整个页面,导致内容变得非常小,视力6.0的都不一定看得清楚。
所以Safari浏览器自带了一个当时看起来相当酷的一个功能:双击缩放。你双击页面的时候,浏览器会智能的缩放当前页面到原始大小。
双击缩放的原理就是,当你click一次之后,会经过300ms之后检测是否再有一次click,如果有的话,就会缩放页面。否则的话就是一个click事件。
所以,当你想执行click操作的时候,就感觉到了”卡顿”。如果点击之后100ms之后没有反应,基本就有卡顿的感觉。
-
dblclick事件失效
由于双击缩放的存在,pc端的dblclick事件也失效了。
随着触屏设备的普及,w3c为移动端web新增了touch事件。
最基本的touch事件包括4个事件:
-
touchstart
当在屏幕上按下手指时触发
-
touchmove
当在屏幕上移动手指时触发
-
touchend
当在屏幕上抬起手指时触发
-
touchcancel
当一些更高级别的事件发生的时候(如电话接入或者弹出信息)会取消当前的touch操作,即触发touchcancel。一般会在touchcancel时暂停游戏、存档等操作。
注意:一定是先要触发touchstart
事件,再有可能触发 touchmove
事件。
jQuery的点穿问题?
(点击穿透问题:点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的click事件,蒙层的关闭按钮绑定的是touch事件,而按钮下面元素绑定的是click事件,touch事件触发之后,蒙层消失了,300ms后这个点的click事件fire,event的target自然就是按钮下面的元素,因为按钮跟蒙层一起消失了)
不要混用touch和click,只用touch,最简单的解决方案,完美解决点击穿透问题
(大家都知道移动端的click事件会延迟300ms触发,这时大家可以使用zepto的touch模块,里面定义了一个tap事件,通过绑定tap事件,可以实现点击立即触发的功能)
参考:
https://blog.csdn.net/alex8046/article/details/52299837
https://blog.csdn.net/u012468376/article/details/72808761
什么是观察者模式?
平时有遇到什么兼容性问题?
移动端点透问题
案例如下:
点头事件测试
div是绝对定位的蒙层,并且z-index高于a。而a标签是页面中的一个链接,我们给div绑定tap事件:
$('#haorooms').on('tap',function(){
$('#haorooms').hide();
});
我们点击蒙层时 div正常消失,但是当我们在a标签上点击蒙层时,发现a链接被触发,这就是所谓的点透事件。
原因:
touchstart 早于 touchend 早于click。 亦即click的触发是有延迟的,这个时间大概在300ms左右,也就是说我们tap触发之后蒙层隐藏, 此时 click还没有触发,300ms之后由于蒙层隐藏,我们的click触发到了下面的a链接上。
解决:
(1)尽量都使用touch事件来替换click事件。例如用touchend事件(推荐)。
(2)用fastclick,https://github.com/ftlabs/fastclick
(3)用preventDefault阻止a标签的click
(4)延迟一定的时间(300ms+)来处理事件 (不推荐)
(5)以上一般都能解决,实在不行就换成click事件。
下面介绍一下touchend事件,如下:
$("#haorooms").on("touchend",function(event) {
event.preventDefault();
});
参考:https://www.jianshu.com/p/cb2d8ca8cff2
http是什么以及组成部分,200和304?
Vue双向绑定的原理?
Vue刷新出现双括号闪动?
怎么解决,多个环境(开发,测试,预生产,生产)的url切换?
什么是BEM?
你的class命名和团队成员class的命名冲突,如何处理?
https://my.oschina.net/u/2600761/blog/1609132
拓展:https://developer.mozilla.org/zh-CN/docs/Web/CSS/@namespace
你平时做接口调试是如何进行,如果后端没有做好接口时你如何进行调试?
jQuery常见面试问题?
Vue常见面试问题?
https://blog.csdn.net/a1426152747/article/details/79727777
小程序常见面试问题?
https://blog.csdn.net/lijiajun95/article/details/54340955
https://blog.csdn.net/qq_40143330/article/details/79644022
ES6常见面试问题:https://www.cnblogs.com/fengxiongZz/p/8191503.html
Javascript和jQuery常用方法总结?