前端面试题

一、this及this指向

在这里插入图片描述

1. 普通函数的this指向

函数的this指向遵循一个基本原则:谁调用的函数,函数的this就指向谁,否则指向全局

window.name = 'yuguang';

var getName = function(){
    console.log(this.name);
};

getName(); // yuguang
2. 箭头函数的this指向

首先我们要知道,箭头函数本身是没有 this,箭头函数 this 是定义箭头函数时父级作用域的 this,也就是说使用箭头函数时,箭头函数内部的 this,我们只需要看定义该箭头函数时,该箭头函数父级的 this 即可

this.val = 2;
var obj = {
    val: 1,
    getVal: () => {
        console.log(this.val);
    }
}

obj.getVal(); // 2
3. call/apply/bind

call、apply、bind可以改变函数内部的this指向,但由于箭头函数自身没有this,所以call、apply、bind对箭头函数是不起作用的

var obj1 = {
    name: 1,
    getName: function (num = '') {
        return this.name + num;
    }
};

var obj2 = {
    name: 2,
};
// 可以理解成在 obj2的作用域下调用了 obj1.getName()函数
console.log(obj1.getName()); // 1
console.log(obj1.getName.call(obj2, 2)); // 2 + 2 = 4
console.log(obj1.getName.apply(obj2, [2])); // 2 + 2 = 4

二、for…in和for…of的区别

for … of是作为ES6新增的遍历方式,允许遍历一个含有iterator接口的数据结构并且返回各项的值,和ES3中的for … in的区别如下
1、for … of遍历获取的是对象的键值,for … in 获取的是对象的键名
2、for … in会遍历对象的整个原型链,性能非常差不推荐使用,而for … of只遍历当前对象不会遍历原型链
3、对于数组的遍历,for … in会返回数组中所有可枚举的属性(包括原型链上可枚举的属性),for … of只返回数组的下标对应的属性值
4、如果要使用for…of遍历普通对象,需要配合Object.keys()一起使用。

var person={
    name:'coco',
    age:22,
    locate:{
        country:'China',
        city:'beijing',
    }
}
for(var key of Object.keys(person)){
    //使用Object.keys()方法获取对象key的数组
    console.log(key+": "+person[key]);//name: coco,age: 22,locate: [object Object]
}

三、事件委托

在这里插入图片描述

事件委托,又名事件代理。事件委托就是利用事件冒泡,就是把子元素的事件都绑定到父元素上。如果子元素阻止了事件冒泡,那么委托也就没法实现了。
好处:提高性能,减少了事件绑定,从而减少内存占用。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .active{
            color: red;
        }
        
    </style>
</head>
<body>
    <ul>
        <li>111</li>
        <li>222</li>
        <li>333</li>
        <li>444</li>
        <li>555</li>
    </ul>
</body>
</html>
<script>
    var ul = document.querySelector('ul');
    var lis = document.querySelectorAll("li");
    ul.onclick = function(e){
        // console.log(e.target);
        lis.className = ""
        let i = e.target;
        i.className = 'active'
        lis = i;
    }
</script>

四、数组去重

1. ES6-set方法
var arr  = [1,23,41,23,45,67true{},{},true,false];
 
function getSet(arr){
return  [...new Set(arr)];
//或者
//return  Array.from(new Set(arr));
}
getSet(arr); 
2.利用Map数据结构去重

创建一个空Map数据结构,遍历需要去重的数组,把数组的每一个元素作为key存到Map中。由于Map中不会出现相同的key值,所以最终得到的就是去重后的结果。

function getArr(arr) {
  let map = new Map();
  let array = new Array();  // 数组用于返回结果
  for (let i = 0; i < arr.length; i++) {
    if(map .has(arr[i])) {  // 如果有该key值
      map .set(arr[i], true);
    } else {
      map .set(arr[i], false);   // 如果没有该key值
      array .push(arr[i]);
    }
  }
  return array ;
}

 console.log(getArr(arr));
3. forEach + indexOf
function getArr(arr){
var res = [];
arr.forEach((val,index)=>{
if( res.indexOf(val) === -1 ){
res.push(val);
}
});
return res;
}

console.log(getArr(arr));

五、对象和面向对象

对象:属性和方法的集合叫做对象(万物皆对象)
面向对象:是一种编程思想,有类、封装、继承、多态的概念

封装:低耦合高内聚

多态:重载和重写

​ 重载:js中是没有重载概念的(后端:方法名相同,但是形参个数不同或者类型不一样,挥着返回值不同(类型),根据传参不同,实现不同的效果

​ 重写:在类的继承中,子类是可以重写父类的方法的

六、数组扁平化

概念:

数组扁平化就是将一个多维数组转换为一个一维数组

实现方式:

利用递归实现

let arr = [1, [2, [3, 4]]];
 
 function flattern(arr) {
        let result = [];
        for(let i = 0; i < arr.length; i++) {
            if(Array.isArray(arr[i])) {
                flattern(arr[i])
            } else {
                result.push(arr[i])
            }
        }
        return result;
    }

ES6 增加了扩展运算符,用于取出参数对象的所有可遍历属性,拷贝到当前对象之中,所以也可以递归扁平化数组,代码如下:


let arr = [1, [2, [3, 4]]];
 
function flatten(arr) {
 
    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr);
    }  //ES6新方法
 
    return arr;
}

七、垃圾回收机制

概念:

浏览器的 Javascript 具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存。其原理是:垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。但是这个过程不是实时的,因为其开销比较大并且GC时停止响应其他操作,所以垃圾回收器会按照固定的时间间隔周期性的执行。

处在闭包中的变量是无法被回收的,容易造成内存堆积

实现原理

js中最常用的垃圾回收方式就是标记清除。当变量进入环境时,例如,在函数中声明一个变量,就将这个变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为“离开环境”。

八、iframe的优缺点有哪些

优点:
  • iframe能够原封不动地把嵌入的网页展现出来。
  • 如果有多个网页调用iframe,只需要修改iframe的内容,就可以实现对调用iframe的每一个页面内容的更改,方便快捷。
  • 如果遇到加载缓慢的第三方内容,如图标和广告等,可以用iframe来解决。
  • 模块分离,便于更改,如果有多个网页引用iframe,只需要修改iframe的内容,就可以实现调用的每一个页面内容的更改,方便快捷;
缺点:
  • 样式和脚本需要额外链入,调用外部页面,需要额外调用css,增加页面额外的请求次数,增加服务器的http请求;

  • 代码复杂,在网页中使用框架结构最大的弊病是搜索引擎的“蜘蛛”程序无法解读这种页面,会影响搜索引擎优化,不利于网站排名;

  • 框架结构有时会让人感到迷惑,滚动条除了会挤占有限的页面空间外会使iframe布局混乱,还会分散访问者的注意力,影响用户体验;

  • 链接导航疑问。运用框架结构时,必须保证正确配置所有的导航链接,否则,会给访问者带来很大的麻烦。比如被链接的页面出现在导航框架内,这种情况下访问者便被陷住了,因为此时他没有其他地点可去;

九、函数柯里化(卡瑞化、加里化)

概念:

”函数柯里化”是指将多变量函数拆解为单变量的多个函数的依次调用, 可以从高元函数动态地生成批量的低元的函数。简单讲:就是利用函数执行,可以形成一个不销毁的私有作用域,把预先处理的内容都存在这个不销毁的作用域里面,并且返回一个函数,以后要执行的就是这个函数。

// 常规的add函数
function add(a, b) {
    return a + b
}

// Currying后
function curryingAdd(a) {
    return function (b) {
        return a + b
    }
}

add(1, 2)           // 3
curryingAdd(1)(2)   // 3

十、window的onload事件

window.onload是一个事件,当文档加载完成之后就会触发该事件


window.onload = function () {
    console.log('执行了1');
};
window.onload = function () {
    console.log('执行2');   //被执行了
}

window.οnlοad=function(){}方法只能运行一个,后一个会覆盖前一个。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值