前端面试题大杂烩(一)

前段时间为了面试,我也是猛刷了许多的面经,自己也总结了一些,决定写成博客,既能重新复习一下,又能和大家分享。

1、继承的几种方式(优缺点)

1)ES6中的class

	class A{
        constructor(name,age){
            this.name = name;
            this.age = age;
        }
        sayHello(){
            console.log("Hello "+this.name);
        }
    }
    class B extends A{      // B继承A
        constructor(name,age,major,){
            super(name,age);
            this.major = major;
        }
    }
    let b = new B('EmailyT',23,'计算机');
    b.sayHello()    //Hello EmailyT

2)原型链方式继承

	 function fn() {
        this.name = 'EmailyT';
        this.age = 23;
    }
    fn.prototype.sex = 'female';
    function fn1() {
        this.major = "计算机科学与技术";
    }
    fn1.prototype = new fn();
    let f = new fn1();
    console.log(f.name)

缺点:
①、不能向父类传参数
②、原型继承,会引发原型共享的问题(改动原型上内容)一处更改,其他也会变

3)借用构造函数

	function fn(name,age) {
        this.name = name;
        this.age = age;
    }
    function fn1(name,age,major) {
        fn.call(this,name,age);
        this.major = major;
    }
    let f = new fn1('EmailyT',23,'计算机');
    console.log(f.name,f.age,f.major)   // EmailyT 23 计算机

优点:可以解决原型继承无法传参的问题
缺点:每个子类继承时都会创建一个,无法实现函数复用

4)组合继承(原型+构造)

	function fn(name,age) {
        this.name = name;
        this.age = age;
    }
   + fn.prototype.sex = 'female';
    function fn1(name,age,major) {
        fn.call(this,name,age);  ②
        this.major = major;
    }
   + fn1.prototype = new fn();   ①   //如果这行不写的话,就不会得到 'sex'
   + fn1.prototype.constructor = fn1;
    let f = new fn1('EmailyT',23,'计算机');
    console.log(f.sex)   //female

优点:既可以传参数,又可以继承原型上的内容
缺点:两次调用了父类(标注的地方)

5)寄生式继承

   function createfn(origin) {
        let obj = Object(origin);  //创建时需要传入一个父类,复制一份
        obj.sayHi = function () {  //自己拥有的方法
            console.log('Hi')
        };
        return obj;
    }
    let parent = {
        name:"EamilyT",
        age:23,
    };
    let child = new createfn(parent);
    console.log(child.name)

6)寄生组合式继承

	function createfn(child,parent) {
        let obj = Object(parent.prototype); //创建副本subP.prototype=parent.prototype 
        obj.constructor = child; //改变指向
        child.prototype = obj;
    }
    function sub(names,age) {
        this.names = names;
        this.age = age;
    }
    sub.prototype.sex = 'female';
    function superP(names,age) {
        sub.call(this,names,age);
    }
    createfn(superP,sub);
    let c = new superP('EmailyT',23);
    console.log(c.names,c.sex); //也可以继承原型属性

2、扁平化数组

let arr = [1,2,[3,[4,5],6],[7,8],9];   //全局数组

1、使用flat()
	arr = arr.flat(4) //参数是数组嵌套的层数
	arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
如果嵌套的层数过多,可以传一个值:arr.flat(Infinity)  

2、使用concat连接数组(循环判断)
	let res = [];  //创建新数组
    function flat(arr) {
        for (let i = 0;i<arr.length;i++){
            if (Array.isArray(arr[i])){  //循环判断当前元素是不是数组
                res.concat(flat(arr[i]));
            }else{
                res.push(arr[i])  //不是则添加
            }
        }
        return res;
    }
3、使用toString+split
	function flat(arr) {
        return arr.toString().split(',').map(function(item) {  
            return Number(item);
        })
    }

3、js的事件模型

1)DOM0级事件:是将事件直接绑定到元素上,比如:

<button "handle()" id="btn">按钮</button>
//js
function handle(){  //绑定
	//...
}
//移除事件:element.onclick = null

DOM0级事件的好处是兼容所有的浏览器,但是没有事件流(冒泡、捕获)

2)DOM1级事件:通过addEventListener()添加,比如:

let btn = document.getElementById('btn');
btn.addEventListener('click',function(){
	//...
},false)

//移除事件监听:removeEventListener

DOM1级事件有三个阶段:事件捕获、事件处理、事件冒泡

3)IE事件:通过attachEvent()添加

let btn = document.getElementById('btn');
btn.attachEvent('onClick',fu)  //这里是“onclick”和DOM2级不一样
//移除事件监听
btn.detachEvent()

IE只有事件捕获这事件冒泡阶段

4、new的过程(以及实现)

  1. 首先会创建一个新的对象
  2. 将新创建的对象的_proto_指向构造函数的原型
  3. 为this对象添加属性和方法
  4. return 对象

代码实现:

function new(fn){
	let obj = {};
	obj._proto_ = fn.prototype;
	let res = fn.call(obj);
	if(typeof res =='object' || typeof res == 'function'){
		return res;
	}
	return obj;
}

5、BFC以及形成的原因(和效果)

  BFC:块级格式化上下文

有什么效果:

  1. BFC元素垂直方向依次排列,上下两个元素边距会发生重叠
  2. 可以用来清楚浮动
  3. BFC是个独立的区域,块内的子元素不会影响外面的内容,反之亦然
  4. BFC区域并不会和float元素重叠

形成的因素:

  1. overflow的值不为visibility
  2. float元素
  3. 定位元素position的值为absolute、fixed
  4. display的值为inline-block、flex、table-cell…

垂直方向元素的margin重叠问题:

  1. 值都为正情况:取最大值
  2. 值都为负情况:取绝对值之后的最大值
  3. 值一正一负情况:两者相加之后的值

6、箭头函数和普通函数的区别

1、箭头函数的this指向规则

  大家都知道箭头函数中没有this,this指向的是箭头函数外的第一个普通函数,那么为什么箭头函数没有this呢?因为箭头函数没有原型 prototype,so

let a = ()=>{return 1};
console.log(a.prototype)  //打印undefined

  刚才也说了,箭头函数中的this是指向外层的普通函数,并且也不能改变箭头函数中的this,只能改变外层的普通函数的this指向,那么来测试看看吧!

var obj = {
    t:function(){
        console.log(this)
    },
    ac:function(){
        setTimeout(()=>{
            console.log(this)
        },100)
    }
}
obj.t();  //{t: ƒ, ac: ƒ}
obj.ac()  //{t: ƒ, ac: ƒ}

在严格模式下还是非严格模式下如果箭头函数外边没有普通函数,那么this都指向window

2、arguments的使用问题

  我们已经了解到,箭头函数中没有this,那么肯定也没有自己的arguments,但是它可以使用外层函数的arguments。

//箭头函数没有自己的arguments,想不报错的话,可以声明一个变量
let fn = ()=>{
    console.log(arguments)
}
fn(1,2)   //arguments is not defined
function bar() {
    console.log(arguments); // ['外层第二个普通函数的参数']
    bb('外层第一个普通函数的参数');
    function bb() {
        console.log(arguments); // ["外层第一个普通函数的参数"]
        let a = () => {
            console.log(arguments); // ["外层第一个普通函数的参数"] this继承外层的普通函数
        };
        a('箭头函数的参数'); // this指向bb
    }
}
bar('外层第二个普通函数的参数');

3、箭头函数不支持new、不支持参数重名

let a = ()=>{ }
let c = new a()   // a is not a constructor
//另外,箭头函数没有原型,同时也没有constructor

//参数问题
let a = (c,c)=>{
    console.log(c)  //报错,Duplicate parameter name not allowed in this context
}
a(1,2)

  以上是箭头函数的一些特性,这有更全的?博客,大家可以看看,总结的挺全。

7、不借助辅助空间情况下,找出不重复的元素

let arr = [0,0,1,1,1,2,3,4,5,5];
let i = 0,j=0;
for(i = 0;i<arr.length;i++){
    for(j = 0;j<arr.length;j++){
        if(arr[i]==arr[j] && i!=j){  //自身不和自身比较
           break;  //一旦相同,立即退出
        }
    }
    if(j==arr.length) console.log(arr[i])  //如果相等,说明没有重复的元素,输出即可
}
//结果为:2,3,5

  这是我目前想出来的一种,欢迎大家补充其他高效的方法。

  这次呢,就先分享这些,等到下篇博客我会继续为大家分享。有意见不同的地方,欢迎大家留言讨论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值