前端知识点

前端面试必掌握问题@令狐张豪

2019-08-07  本文已影响57人  令狐张豪

什么是闭包,优缺点?

闭包实际上就是一个嵌套函数,在一个函数内定义的一个函数。作为闭包的必要条件,内部函数应该访问外部函数中声明的私有变量、参数或者其他内部函数。当上述的两个条件实现后,此时如果在外部函数外调用这个内部函数,他就是成为了闭包函数。

【实例】 本例是一个经典的闭包结构
<script>
    function fn(x) {             //外部函数
        var a = x;               //外部函数的局部变量,并把参数值传递给它
        var b = function () {    //内部函数
            return a;            //内部函数访问外部函数的局部变量
        }           
        a++;                     //访问后,动态更新外部函数的变量
        return b;                //外部函数返回内部函数
    }
    var c = fn(5);
    console.log(c())
</script>

闭包的优点

  1. 方便调用上下文的局部变量
  2. 加强了封装性,可以达到对变量的保护作用
  3. 逻辑连续,当闭包作为另一个函数调用参数时,避免脱离当前逻辑而单独编写额外逻辑

闭包的缺点

  1. 由于闭包是驻留在内存中,会增大内存使用量,使用不当很容易造成内存泄露,降低程序的性能

三栏布局,都有几种?


什么是原型链?原型链怎么实现继承?

定义原型

原型:声明函数时js会自动生成prototype,prototype会生成一个空对象(也就是原型对象),原型对象的constructor默认为你声明的对象

原型链.PNG
原型链

原型链:从实例往上寻找构造这个实例的相关联的对象,然后在这个关联的对象在往上查找创建它的上一级的原型对象,以此类推,一直到object.prototype终止,object.prototype是原型链的顶端。

任何一个实例对象通过原型链找到它上面的原型对象,这个原型对象上的方法和属性都被实例共享,这就是原型链的原理

原型链实现继承的几种方法
借用构造函数继承
function SuperType () {
  this.colors = ["red", "blue", "green"]
}
function SubType () {
  // 继承了SuperType
  SuperType.call(this)
  // 只能继承构造函数上的属性
}
  1. 函数复用性不高
  2. 只能继承实例上的属性,原型上的方法不可见
组合继承(伪经典继承)
function SuperType (name) {
  this.name = name
  this.colors = ["red", "blue", "green"]
}
SuperType.prototype.sayName = function () {
  alert(this.name)
}
function SubType (name, age) {
  // 继承属性
  SuperType.call(this, name) // 第二次调用SuperType()
  this.age = age
}
//继承方法
SubType.prototype = new SuperType() // 第一次调用 SuperType()
Subtype.prototype.sayAge = function () {
  alert(this.age)
}
  1. 组合继承避免了原型链和借用构造函数的缺陷,融合了他们的优点,成为js中最常用的继承方式。
原型式继承
function object (o) {
  function F(){}
  F.prototype = o
  return new F()
}
  1. 可以在不必预先定义构造函数的情况下实现继承,其本质是执行对给定对象的浅复制,而复制的副本还可以得到进一步的改造
    问题还是包含引用类型的属性都会被共享。
寄生式继承
function createAnother (original) {
  var clone = object(original) // 通过调用函数创建一个新对象
  clone.sayHi = function () { // 以某种方式来增强这个对象
    alert("hi")
  }
  return clone // 返回这个对象
}
  1. 基于某个对象或者某些信息创建一个对象,然后增强对象,最后返回对象,为了解决组合继承模式由于多次调用超类型构造函数而导致的低效率问题,可以将这个模式与组合继承一起使用
寄生组合式继承
function inheritPrototype (subType, superType) {
  var prototype = object(superType.prototype) // 创建对象
  prototype.constructor = subType // 增强对象
  subType.prototype = prototype // 指定对象
}

function SuperType (name) {
  this.name = name
  this.colors = {"red", "blue", "green"}
}
SuperType.prototype.sayName = function () {
  alert(this.name)
}
function SubType (name, age) {
SuperType.call(this, name)
  this.age = age
}
inheritPrototype(SubType, SuperType)
  1. 高效率只调用了一次构造函数,集寄生式继承和组合继承的优点于一身,是实现基于类型继承的最有效方式

什么是深拷贝什么是浅拷贝?

在了解深拷贝和浅拷贝之前我们先来了解一下堆和栈

堆stack 和 栈heap

什么是堆内存&&什么是栈内存?
深拷贝和浅拷贝

使用场景:
深拷贝:在复杂对象里,对象的属性也是对象的时候;
浅拷贝:只复制一层对象,当对象的属性是引用类型时,实质上复制的是其引用,当引用指向的值发生变化的时候,原对象属性值也跟着变化;

浅拷贝

将原对象/原数组的引用,直接赋给新对象/新数组,新对象/数组只是原对象的一个引用


    
        let obj={a:1,arr:[2,3]};    
 
        let shallowObj=shallowCopy(obj);
        
        function shallowCopy(srcObj){
            var dest={};
            for(let prop in srcObj){
                    console.log(prop);
                if(srcObj.hasOwnProperty(prop)){
                    dest[prop]=srcObj[prop]
                    
 
                    }
 
                }// end of loop
                
                return dest;
            } 
        
//  当一个对象属性的引用值改变时,会导致另一个也改变;
    
    shallowObj.arr[1]=5;

深拷贝

深拷贝就是将原有对象重新拷贝一份,不论是修改哪一部分的值,都不会对原有对象造成影响。拷贝的永远是值,而不是引用。


你是怎么做响应式布局的?

什么是响应式布局?

简而言之,就是一个网站能够兼容多个终端——而不是为每个终端做一个特定的版本。


令狐张豪.jpg
优点:
缺点:
响应式设计——设置 Meta 标签

大多数移动浏览器将HTML页面放大为宽的视图(viewport)以符合屏幕分辨率。你可以使用视图的meta标签来进行重置。下面的视图标签告诉浏览器,使用设备的宽度作为视图宽度并禁止初始的缩放。在<head>标签里加入这个meta标签

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
viewport

通俗的讲,移动设备上的viewport就是设备的屏幕上能用来显示我们的网页的那一块区域,在具体一点,就是浏览器上(也可能是一个app中的webview)用来显示网页的那部分区域

content属性值

你是怎么用rem做自适应的?

什么是rem?

说到rem自然就会想到em,我们知道em是相对于父元素的字体大小的单位,那么rem则是相对于根元素也就是<html>元素的字体大小的单位。

如何用rem解决移动端适配
script方法
<script>
    window.addEventListener('orientationchange', setRem);
    window.addEventListener('resize', setRem);
    setRem();
    function setRem() {
        var html = document.querySelector('html');
        var width = html.getBoundingClientRect().width;
        html.style.fontSize = width / 16 + 'px';
    };
</script>

style方法
<style>
    // sass写法
    @function rem($px) {
        @return $px / 46.875 + rem;
    }
    //less写法
    @rem: 46.875rem;
    //stylus自行解决
    ?
</style>
用法:

如:元素宽300px,高500px;
传入参数即可:width:rem(300); height:rem(500);


vue的双向数据绑定

所谓双向数据绑定, 无非就是数据层和视图层中的数据同步, 在写入数据时视图层实时的跟着更新

实现mvvm的双向绑定,是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。就必须要实现以下几点:

  1. 实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
  2. 实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
  3. 实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
  4. mvvm入口函数,整合以上三者


    令狐张豪.png

说说vuex

什么是vuex?

是专门一个为vue.js应用程序开发的状态管理模式

vuex的运行机制
前端小学生.jpg

如何使用promise封装axios?

class Http {
  //request 方法
  request(params) {
    return new Promise((resolve, reject) => {
      Axios({
         method: params.type || "get", //请求的方式
         url: params.url,              //请求的地址
         data: params.data,            //post 传的参数
        headers: params.headers       //headers 请求头
      }) 
        .then(res => { //请求成功触发
          if (res.data.code === 0) {
            resolve(res);
          } else {
            resolve(res);
          }
        })
        .catch(err => {
          reject(err.statusText); ///请求失败触发
        });
    });
  }
}
解释

浏览器兼容问题如何解决?

Normalize.css

不同浏览器的默认样式存在差异,可以使用 Normalize.css 抹平这些差异。当然,你也可以定制属于自己业务的 reset.css

<link href="https://cdn.bootcss.com/normalize/7.0.0/normalize.min.css" rel="stylesheet">
html5shiv.js

解决 ie9 以下浏览器对 html5 新增标签不识别的问题。

<script type="text/javascript" src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
respond.js

解决 ie9 以下浏览器不支持 CSS3 Media Query 的问题。

<script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>

详细查看解决方案


git常用指令

初始化git

git init

关联库

git remote add origin

克隆别人的项目

git clone

编写完之后提交到库里(更新)
  • 先合并 git pull
  • 再查状态 git status
  • 给你新写的内容加入缓存区 git add .
  • 起别名 git commit -m 'linghu'
  • 给他提交到库里 git push

一面二面详细视频链接(提取码:l10y)

上一篇 下一篇

猜你喜欢

热点阅读