2019年前端面试题-03

  1. let与var的区别?
    Let为ES6新添加申明变量的命令,它相似于var,可是有如下不一样:
    一、var声明的变量,其做用域为该语句所在的函数内,且存在变量提高现象
    二、let声明的变量,其做用域为该语句所在的代码块内,不存在变量提高
    三、let不容许重复声明.
  2. 封装一个函数,参数是定时器的时间,.then执行回调函数。javascript

    function sleep (time) { 
    return new Promise((resolve) => setTimeout(resolve, time));
    }
  3. 项目作过哪些性能优化?
    一、减小HTTP请求数
    二、减小DNS查询
    三、使用CDN
    四、避免重定向
    五、图片懒加载
    六、减小DOM元素数量
    七、减小DOM操做
    八、使用外部JavaScript和CSS
    九、压缩JavaScript、CSS、字体、图片等
    十、优化CSS Sprite
    十一、使用iconfont
    十二、字体裁剪
    1三、多域名分发划份内容到不一样域名
    1四、尽可能减小iframe使用
    1五、避免图片src为空
    1六、把样式表放在 中
    1七、把脚本放在页面底部
  4. 怎么判断两个对象相等?
    一、转化成字符串后比较字符串是否一致:php

    JSON.stringify(obj)===JSON.stringify(obj2);

    二、Object.is(obj1,obj2):判断两个值是否 [相同]。若是下列任何一项成立,则两个值相同。css

    * 两个值都是 [undefined]
       * 两个值都是 [null]
       * 两个值都是true或者都是false
       * 两个值是由相同个数的字符按照相同的顺序组成的字符串
       * ~两个值指向同一个对象~
       * 两个值都是数字而且
           * 都是正零+0
           * 都是负零-0
           * 都是 [NaN]
           * 都是除零和[NaN]外的其它同一个数字
  5. 什么是模块化开发?

    实现mvvm主要包含两个方面,数据变化更新视图,视图变化更新数据:
    图片描述html

    关键点在于data如何更新view,由于view更新data其实能够经过事件监听便可,好比input标签监听 'input' 事件就能够实现了。因此咱们着重来分析下,当数据改变,如何更新视图的。
    数据更新视图的重点是如何知道数据变了,只要知道数据变了,那么接下去的事都好处理。如何知道数据变了,其实上文咱们已经给出答案了,就是经过Object.defineProperty( )对属性设置一个set函数,当数据改变了就会来触发这个函数,因此咱们只要将一些须要更新的方法放在这里面就能够实现data更新view了。前端

    Vue是经过Object.defineProperty()来实现数据劫持的。它能够来控制一个对象属性的一些特有操做,好比set()、get()、是否能够枚举。
    图片描述
    实现数据的双向绑定,首先要对数据进行劫持监听,因此咱们须要设置一个监听器Observer,用来监听全部属性。若是属性发上变化了,就须要告诉订阅者Watcher看是否须要更新。由于订阅者是有不少个,因此咱们须要有一个消息订阅器Dep来专门收集这些订阅者,而后在监听器Observer和订阅者Watcher之间进行统一管理的。接着,咱们还须要有一个指令解析器Compile,对每一个节点元素进行扫描和解析,将相关指令对应初始化成一个订阅者Watcher,并替换模板数据或者绑定相应的函数,此时当订阅者Watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。所以接下去咱们执行如下3个步骤,实现数据的双向绑定:
    1.实现一个监听器Observer,用来劫持并监听全部属性,若是有变更的,就通知订阅者。
    2.实现一个订阅者Watcher,能够收到属性的变化通知并执行相应的函数,从而更新视图。
    3.实现一个解析器Compile,能够扫描和解析每一个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。java

    流程图以下:
    图片描述面试

  6. 浏览器兼容性问题
    图片描述
    一、Normalize.css
    二、不一样浏览器的标签默认的外边距和内边距不一样:
    三、IE6双边距问题:在 IE6中设置了float , 同时又设置margin , 就会出现边距问题:设置display:inline;
    四、图片默认有间距:使用float 为img 布局
    五、IE9如下浏览器不能使用opacity:ajax

    opacity: 0.5;
    filter: alpha(opacity = 50);
    filter: progid:DXImageTransform.Microsoft.Alpha(style = 0, opacity = 50);

    六、cursor:hand 显示手型在safari 上不支持:统一使用 cursor:pointer
    七、当标签的高度设置小于10px,在IE六、IE7中会超出本身设置的高度:超出高度的标签设置overflow:hidden,或者设置line-height的值小于你的设置高度
    八、CSS HACK的方法:json

    height: 100px;    // 全部浏览器 通用 
    _height: 100px;    // IE6 专用 
    *+height: 100px;    // IE7 专用 
    *height: 100px;    // IE六、IE7 共用 
    height: 100px !important;        // IE七、FF 共用

    代码的顺序必定不能颠倒了,要不又前功尽弃了。由于浏览器在解释程序的时候,若是重名的话,会用后面的覆盖前面的,就象给变量赋值一个道理,因此咱们把通用的放前面,越专用的越放后面segmentfault

  7. 前端跨域

    1. 什么是跨域?

      >     只要协议、域名、端口有任何一个不一样,都被看成是不一样的域。
      >     同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,所以拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,可是没法被浏览器接收。
      >     之因此会跨域,是由于受到了同源策略的限制,同源策略要求源相同才能正常进行通讯,即协议、域名、端口号都彻底一致。
      > 
      > 注意点:
      > 若是是协议和端口形成的跨域问题“前台”是无能为力的;
      > 在跨域问题上,域仅仅是经过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。 (“URL的首部”指window.location.protocol +window.location.host,也能够理解为“Domains, protocols and ports must match”。)
    2. 什么是同源策略?

      > 所谓同源是指,域名,协议,端口相同。浏览器采用同源策略,就是禁止页面加载或执行与自身来源不一样的域的任何脚本。
    3. 经过document.domain跨域(只适用于不一样子域的框架间的交互)

      浏览器有一个同源策略,其限制之一是不能经过ajax的方法去请求不一样源中的文档。第二个限制是浏览器中不一样域的框架之间是不能进行js的交互操做的。不一样的框架之间是能够获取window对象的,但却没法获取相应的属性和方法。好比,有一个页面,它的地址是 [www.damonare.cn/a.html], 在这个页面里面有一个iframe,它的src是 [damonare.cn/b.html], 很显然,这个页面与它里面的iframe框架是不一样域的,因此咱们是没法经过在页面中书写js代码来获取iframe中的东西的:
    4. 经过location.hash跨域
    5. 经过HTML5的postMessage方法跨域
    6. 经过jsonp跨域

      JSONP的优缺点
          * JSONP的优势是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中均可以运行,不须要XMLHttpRequest或ActiveX的支持;而且在请求完毕后能够经过调用callback的方式回传结果。
          * JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种状况,不能解决不一样域的两个页面之间如何进行JavaScript调用的问题。
    7. 经过CORS跨域

      CORS(Cross-Origin Resource Sharing)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功仍是失败。目前,全部浏览器都支持该功能,IE浏览器不能低于IE10。整个CORS通讯过程,都是浏览器自动完成,不须要用户参与。对于开发者来讲,CORS通讯与同源的AJAX通讯没有差异,代码彻底同样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感受。
    8. 经过window.name跨域

      window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的全部的页面都是共享一个window.name的,每一个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的全部页面中的,并不会因新页面的载入而进行重置。
  8. 前端优化:浏览器缓存

    前端优化:浏览器缓存技术介绍 - 掘金
    浏览器缓存分为强缓存和协商缓存。

    当客户端请求某个资源时,获取缓存的流程以下:
    1)浏览器在加载资源时,先根据这个资源的一些http header判断它是否命中强缓存,强缓存若是命中,浏览器直接从本身的缓存中读取资源,不会发请求到服务器。好比:某个css文件,若是浏览器在加载它所在的网页时,这个css文件的缓存配置命中了强缓存,浏览器就直接从缓存中加载这个css,连请求都不会发送到网页所在服务器;

    2)当强缓存没有命中的时候,浏览器必定会发送一个请求到服务器,经过服务器端依据资源的另一些http header验证这个资源是否命中协商缓存,若是协商缓存命中,服务器会将这个请求返回,可是不会返回这个资源的数据,而是告诉客户端能够直接从缓存中加载这个资源,因而浏览器就又会从本身的缓存中去加载这个资源;

    3)强缓存与协商缓存的共同点是:若是命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据;区别是:强缓存不发请求到服务器,协商缓存会发请求到服务器。

    4)当协商缓存也没有命中的时候,浏览器直接从服务器加载资源数据。

  9. jsonp的原理与实现

    Jsonp是一种跨域通讯的手段,它的原理其实很简单:

    > 1. 首先是利用script标签的src属性来实现跨域。
       > 2. 经过将前端方法做为参数传递到服务器端,而后由服务器端注入参数以后再返回,实现服务器端向客户端通讯。
       > 3. 因为使用script标签的src属性,所以只支持get方法

    实现流程:

    一、设定一个script标签

    <script src="http://jsonp.js?callback=xxx"></script>

    二、callback定义了一个函数名,而远程服务端经过调用指定的函数并传入参数来实现传递参数,将function(response)传递回客户端

    $callback = !empty($_GET['callback']) ? $_GET['callback'] : 'callback';
    echo $callback.'(.json_encode($data).)';

    三、客户端接收到返回的js脚本,开始解析和执行function(response)

    简单的实例:
    一个简单的jsonp实现,其实就是拼接url,而后将动态添加一个script元素到头部。

    function jsonp(req){
        var script = document.createElement('script');
        var url = req.url + '?callback=' + req.callback.name;
        script.src = url;
        document.getElementsByTagName('head')[0].appendChild(script); 
    }

    前端js示例:

    function hello(res){
        alert('hello ' + res.data);
    }
    jsonp({
        url : '',
        callback : hello 
    });

    服务器端代码:

    var http = require('http');
    var urllib = require('url');
    
    var port = 8080;
    var data = {'data':'world'};
    
    http.createServer(function(req,res){
        var params = urllib.parse(req.url,true);
        if(params.query.callback){
            console.log(params.query.callback);
            //jsonp
            var str = params.query.callback + '(' + JSON.stringify(data) + ')';
            res.end(str);
        } else {
            res.end();
        }
        
    }).listen(port,function(){
        console.log('jsonp server is on');
    });

    可靠的jsonp实例:

    (function (global) {
        var id = 0,
            container = document.getElementsByTagName("head")[0];
    
        function jsonp(options) {
            if(!options || !options.url) return;
    
            var scriptNode = document.createElement("script"),
                data = options.data || {},
                url = options.url,
                callback = options.callback,
                fnName = "jsonp" + id++;
    
            // 添加回调函数
            data["callback"] = fnName;
    
            // 拼接url
            var params = [];
            for (var key in data) {
                params.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key]));
            }
            url = url.indexOf("?") > 0 ? (url + "&") : (url + "?");
            url += params.join("&");
            scriptNode.src = url;
    
            // 传递的是一个匿名的回调函数,要执行的话,暴露为一个全局方法
            global[fnName] = function (ret) {
                callback && callback(ret);
                container.removeChild(scriptNode);
                delete global[fnName];
            }
    
            // 出错处理
            scriptNode.onerror = function () {
                callback && callback({error:"error"});
                container.removeChild(scriptNode);
                global[fnName] && delete global[fnName];
            }
    
            scriptNode.type = "text/javascript";
            container.appendChild(scriptNode)
        }
    
        global.jsonp = jsonp;
    
    })(this);

    使用示例:

    jsonp({
        url : "www.example.com",
        data : {id : 1},
        callback : function (ret) {
            console.log(ret);
        }
    });

欢迎阅读:
2019年前端面试题-01
2019年前端面试题-02
2019年前端笔试题


我是Cloudy,年轻的前端攻城狮一枚,爱专研,爱技术,爱分享。
我的笔记,整理不易,感谢阅读、点赞和收藏。
文章有任何问题欢迎你们指出,也欢迎你们一块儿交流前端各类问题!