前端面试套餐
css:有哪些方式可以隐藏页面元素?区别?
正常人就知道display:none
和visibility:hidden
,它们和vue中的v-if,v-show相对应
但是其实不止这两种哦!
- display:none
元素本身占有的空间会被其他元素占有,会导致浏览器的重排和重绘
元素不可见,不占据空间,无法响应点击事件
- visibility:hidden
从页面上仅仅隐藏元素,DOM结果均会存在,只是当时在一个不可见的状态,不会触发重排,但是会触发重绘
元素不可见,占据空间,无法响应点击事件
- opacity:0
opacity表示元素的透明度,将元素的透明度设置为0后,在我们用户眼中,元素是隐藏的
不会引发重排,一般情况下也会引发重绘
如果利用animation动画,对opacity做变化,则只会触发GPU层面的composite,不会触发重绘
元素不可见,占据页面空间,可以响应点击事件
- 设置height,width模型属性为0
将元素的margin,border,padding,height和width等影响元素盒模型的属性设置成0,如果元素内有子元素或内容,还应该设置其overflow:hidden
来隐藏其子元素
- position:absolute
将元素移出可视区域
.hide {
position: absolute;
top: -9999px;
left: -9999px;
}
元素不可见,不影响页面布局
- clip-path
通过裁剪的形式
.hide {
clip-path: polygon(0px 0px,0px 0px,0px 0px,0px 0px);
}
区别
最常用的还是display:none
和visibility:hidden
对于前三者做一个比较
display:none | visibility:hidden | opacity:0 | |
---|---|---|---|
页面中 | 不存在 | 存在 | 存在 |
重排 | 会 | 不会 | 不会 |
重绘 | 会 | 会 | 不一定 |
自身绑定事件 | 不触发 | 不触发 | 可触发 |
transition | 不支持 | 支持 | 支持 |
子元素可复原 | 不能 | 能 | 不能 |
被遮挡的元素可触发事件 | 能 | 能 | 不能 |
js:说说对闭包的理解?闭包使用场景?
一个函数和对其周围状态的引用捆绑在一起,这样的组合就是闭包。
简单来说,就是在一个内层函数中可以访问到其外层函数的作用域
使用场景
- 创建私有变量
- 延长变量的声明周期
模拟私有方法
var Counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
});
var Counter1 = new Counter();
var Counter2 = new Counter();
console.log(Counter1.value()); /* logs 0 */
Counter1.increment();
Counter1.increment();
console.log(Counter1.value()); /* logs 2 */
Counter1.decrement();
console.log(Counter1.value()); /* logs 1 */
console.log(Counter2.value()); /* logs 0 */
柯里化函数
柯里化的目的在于避免频繁调用具有相同参数函数的同时,又能够轻松的重用
// 假设我们有一个求长方形面积的函数
function getArea(width, height) {
return width * height
}
// 如果我们碰到的长方形的宽老是10
const area1 = getArea(10, 20)
const area2 = getArea(10, 30)
const area3 = getArea(10, 40)
// 我们可以使用闭包柯里化这个计算面积的函数
function getArea(width) {
return height => {
return width * height
}
}
const getTenWidthArea = getArea(10)
// 之后碰到宽度为10的长方形就可以这样计算面积
const area1 = getTenWidthArea(20)
// 而且如果遇到宽度偶尔变化也可以轻松复用
const getTwentyWidthArea = getArea(20)
其他
还在延迟调用,回调中会用到闭包,比如防抖这些
闭包在处理速度和内存消耗方面对脚本性能有负面影响,能不能还是不用吧!
es6:怎么理解ES6中Generator的?使用场景?
Generator函数是ES6提供的一种异步编程解决方案,语法执行与传统函数完全不同
为什么有promise存在了,还出现Generator呢?
让我们一探究竟!!!
执行Generator函数会返回一个遍历器对象,可以一次遍历Generator函数内部的每一个状态
形式上,Generator函数是一个普通函数,但是又两个特征:
- function关键字与函数名之间有一个星号
- 函数体内部使用yield表达式,定义不同的内部状态
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
- 通过
next
方法遍历内部状态- 遇到
yield
表达式,就暂停执行后面的操作,并将紧跟在yield
后面的那个表达式的值,作为返回的对象的value属性值 - 下次调用
next
方法时,再继续往下执行,知道遇到下一个yield
表达式 - 如果没遇到新的yield表达式,就一直运行到函数结束,知道return语句位置,并将return语句后面的表达式的值,作为返回对象的value属性值
- 如果该函数没有return语句,则返回对象的value属性值为undefined
done
用来判断是否存在下个状态,value对应状态值
- 遇到
var hw = helloWorldGenerator();
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
function* foo(x) {
var y = 2 * (yield (x + 1));
var z = yield (y / 3);
console.log(x,y,z);
return (x + y + z);
}
var a = foo(5);
console.log(a.next() );
console.log(a.next() );
console.log(a.next() );
var b = foo(5);
console.log(b.next() );
console.log(b.next(12) );
console.log(b.next(13) ); // 42=5+24+13
- 我们还可以用
for...of
遍历generator
函数返回的iterator
对象
使用场景
将异步操作同步化表达出来
function* loadUI() {
showLoadingScreen();
yield loadUIDataAsynchronously();
hideLoadingScreen();
}
var loader = loadUI();
// 加载UI
loader.next()
// 卸载UI
loader.next()
vue:为什么Vue中的v-if和v-for不建议一起用?
作用
v-if
指令用于条件性地渲染一块内容。这块内容只会再指令地表达式返回true
值得时候被渲染v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用item in items
形式得特殊语法,其中items
是原数据数组或对象,而item
则是被迭代的数组元素的别名- 在
v-for
的时候,建议设置key值,并且保证每个key值独一无二,这便于diff算法进行优化
这里要看源码,比较麻烦。我们直接说结论,就是v-for
优先级比v-if
高
如果放在同一个元素上,那么每一个v-for的元素都用一次v-if,效率很低
注意事项
- 永远不要把
v-if
和v-for
同时用在同一个元素上,带上性能方面的浪费(每次渲染都会先循环再进行条件判断) - 我们再外层嵌套template(页面渲染不生成dom节点),在这一层进行
v-if
判断,然后在内部进行v-for
循环