前端面试题(八)

  • 浏览器内多个标签页之间的通讯方式有哪些

    这个问题没有进行过多的研究, 借阅一下别人的答案 网页消息通讯
    1. WebSocket (可跨域)
      WebSocket 是 HTML5 开始提供的一种在单个 TCP 链接上进行全双工通信的协议。
    2. postMessage(可跨域)
      window.postMessage()方法安全地启用Window对象之间的跨源通讯git

      对将接收消息的窗口的引用,得到此类引用的方法包括:github

      1. iframe标签
      2. Window.open (生成一个新窗口而后引用它)
      3. Window.opener (引用产生这个的窗口)
    3. Worker之SharedWorker
      做为浏览器的一个新特性,能够提供一个额外的线程来执行一些js代码(真正的多线程),而且不会影响到浏览器用户界面,可是不能DOM操做。web

      SharedWorker能够被多个window共同使用,因此能够用来跨页面传输数据,但必须保证这些标签页都是同源的(相同的协议,主机和端口号)
    4. Server-Sent Events
      HTML5 服务器发送事件(server-sent event)容许网页得到来自服务器的更新。Server-Sent 事件指的是网页自动获取来自服务器的更新。之前也可能作到这一点,前提是网页不得不询问是否有可用的更新。经过服务器发送事件,更新可以自动到达
    5. localStorage
      localstorage是浏览器多个标签共用的存储空间,因此能够用来实现多标签之间的通讯(ps:session是会话级的存储空间,每一个标签页都是单独的)。 直接在window对象上添加监听便可。
    6. BroadcastChannel
      这个方式,只要是在同一原始域和用户代理下,全部窗口、iframe之间均可以进行交互。这个感受就有点相似于广播了。
    7. Cookies
      Cookies在同一个域名内,而且目录也得相同

  • 简述你理解的优雅降级和逐渐加强

    优雅降级:面试

    先不考虑兼容,优先最新版本浏览器效果,以后再逐渐兼容低版本浏览器

    逐渐加强:json

    考虑兼容,以较低(多)浏览器效果为主,以后再逐渐增长对新版本浏览器的支持,之内容为主。也是多数公司所采用的方法。

  • 写一个判断数据类型的方法

    通常来讲有这么几种办法, 可是有着各自的一些缺陷
    1. typeof
    若是使用 typeof 来判断数据类型的话:跨域

    console.log(
        typeof 123, //"number"
        typeof 'dsfsf', //"string"
        typeof false, //"boolean"
        typeof [1,2,3], //"object"
        typeof {a:1,b:2,c:3}, //"object"
        typeof function(){console.log('aaa');}, //"function"
        typeof undefined, //"undefined"
        typeof null, //"object"
        typeof new Date(), //"object"
        typeof /^[a-zA-Z]{5,20}$/, //"object"
        typeof new Error() //"object"
    );

    经过上面的测试发现:浏览器

    Array,Object,null,Date,RegExp,Error这几个类型都被typeof判断为object,因此若是想要判断这几种类型,就不能使用typeof了。
    Number,String,Boolean,Function,undefined,若是想判断这几种类型,那就可使用typeof

    2. instanceof
    instanceof运算符须要指定一个构造函数,或者说指定一个特定的类型,它用来判断这个构造函数的原型是否在给定对象的原型链上。安全

    console.log(
        123 instanceof Number, //false
        'dsfsf' instanceof String, //false
        false instanceof Boolean, //false
        [1,2,3] instanceof Array, //true
        {a:1,b:2,c:3} instanceof Object, //true
        function(){console.log('aaa');} instanceof Function, //true
        undefined instanceof Object, //false
        null instanceof Object, //false
        new Date() instanceof Date, //true
        /^[a-zA-Z]{5,20}$/ instanceof RegExp, //true
        new Error() instanceof Error //true
    )

    能够发现:服务器

    Number,String,Boolean没有检测出他们的类型,可是若是使用下面的写法则能够检测出来:
    var num = new Number(123);
    var str = new String('dsfsf');
    var boolean = new Boolean(false);
    还须要注意null和undefined都返回了false,这是由于它们的类型就是本身自己,并非Object建立出来它们,因此返回了false。

    3. constructor
    constructor是prototype对象上的属性,指向构造函数。根据实例对象寻找属性的顺序,若实例对象上没有实例属性或方法时,就去原型链上寻找,所以,实例对象也是能使用constructor属性的.
    若是输出一个类型的实例的constructor,就以下所示:session

    console.log(new Number(123).constructor)
    //ƒ Number() { [native code] }

    能够看到它指向了Number的构造函数,所以,可使用num.constructor==Number来判断一个变量是否是Number类型的。

    var num  = 123;
    var str  = 'abcdef';
    var bool = true;
    var arr  = [1, 2, 3, 4];
    var json = {name:'wenzi', age:25};
    var func = function(){ console.log('this is function'); }
    var und  = undefined;
    var nul  = null;
    var date = new Date();
    var reg  = /^[a-zA-Z]{5,20}$/;
    var error= new Error();
    
    function Person(){
    
    }
    var tom = new Person();
    
    // undefined和null没有constructor属性
    console.log(
        tom.constructor==Person,
        num.constructor==Number,
        str.constructor==String,
        bool.constructor==Boolean,
        arr.constructor==Array,
        json.constructor==Object,
        func.constructor==Function,
        date.constructor==Date,
        reg.constructor==RegExp,
        error.constructor==Error
    );
    //全部结果均为true
    除了undefined和null以外,其余类型均可以经过constructor属性来判断类型。

    4. 使用toString()检测对象类型
    能够经过toString() 来获取每一个对象的类型。为了每一个对象都能经过 Object.prototype.toString() 来检测,须要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象做为第一个参数,称为thisArg。

    var toString = Object.prototype.toString;
    
    toString.call(123); //"[object Number]"
    toString.call('abcdef'); //"[object String]"
    toString.call(true); //"[object Boolean]"
    toString.call([1, 2, 3, 4]); //"[object Array]"
    toString.call({name:'wenzi', age:25}); //"[object Object]"
    toString.call(function(){ console.log('this is function'); }); //"[object Function]"
    toString.call(undefined); //"[object Undefined]"
    toString.call(null); //"[object Null]"
    toString.call(new Date()); //"[object Date]"
    toString.call(/^[a-zA-Z]{5,20}$/); //"[object RegExp]"
    toString.call(new Error()); //"[object Error]"
    这样能够看到使用Object.prototype.toString.call()的方式来判断一个变量的类型是最准确的方法。

    综上所述
    封装一个获取变量准确类型的函数:

    function gettype(obj) {
      var type = typeof obj;
    
      if (type !== 'object') {
        return type;
      }
      //若是不是object类型的数据,直接用typeof就能判断出来
    
      //若是是object类型数据,准确判断类型必须使用Object.prototype.toString.call(obj)的方式才能判断
      return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');
    }

    这样判断一个变量的数据类型就很方便了。

面试题摘自Github

相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息