欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

js在面试中会遇到的几个问题(下)

程序员文章站 2022-06-10 10:58:59
...

1.iframe的优缺点

首先要知道普通方法加载iframe,它没有浏览器的兼容性问题。

<iframe src="/path/to/file" frameborder="0" width="728" height="90" scrolling="auto"></iframe>

使用这种加载方法会在各浏览器中有如下表现:

  • iframe会在主页面的onload之前加载
  • iframe会在所有iframe的内容都加载完毕之后触发iframe的onload
  • 主页面的onload会在iframes的onload触发之后触发,所以iframe会阻塞主页面的加载。
  • 当iframe在加载的过程中,浏览器会标识正在加载东西,处于忙碌状态。

iframe的好处

  • 代码重复:

因为公司业务以及领导的要求现在的醒目都用的iframe,主要为了代码的重复,导航,底部啊,这样可以不用
每一个页面重复写导航和底部,当改起来的时候也方便。

  • iframes异步加载技术:

加载第三方的内容、广告或者插件经常会使用iframe。使用iframe是因为他可以和主页面并行加载,不会阻塞主页面.iframe采用的是异步加载。

iframe的坏处

  • 性能之阻塞主页面的onLoad事件:

iframe虽然是异步加载不会阻塞主页面的加载,但是iframe会阻塞主页面的onload事件的加载。但是很多的事件都在onLoad事件里,iframe阻塞了主页面的onLoad的事件的加载,就会带来不好的用户体验。

  • 性能之和主页面公用一个连接池:
  • seo:

搜索引擎的蜘蛛不会识别在iframe中被调用的图片、文本、url等内容的,因为该内容不属于该页面,只是访问的时候被临时的调用,而且在SEO建议中也有提到:“frame/frameset/iframee标签,会导致百度spider的抓取困难,建议不要使用”这样更能证明其弊!

2.Ajax的原生写法

  1. 创建ajax对象XMLHttpRequest
  2. 连接到服务器
  3. 发送请求
  4. 接收返回值
var XHR=null;  
if (window.XMLHttpRequest) {  
    // 非IE内核  
    XHR = new XMLHttpRequest();  
} else if (window.ActiveXObject) {  
    // IE内核,这里早期IE的版本写法不同,具体可以查询下  
    XHR = new ActiveXObject("Microsoft.XMLHTTP");  
} else {  
    XHR = null;  
}  

if(XHR){  
    XHR.open("GET", "ajaxServer.action");  

    XHR.onreadystatechange = function () {  
        // readyState值说明  
        // 0,初始化,XHR对象已经创建,还未执行open  
        // 1,请求已经建立,但是还没有发送,已经调用open方法,但是还没发送请求,没有调用send()
        // 2,请求已发送,正在处理中(通常现在可以从响应中获取内容头)。
        // 3,请求在处理中;通常响应中已有部分数据可用了,但是服务器还没有完成响应的生成
        // 4,响应已完成;您可以获取并使用服务器的响应了。

        // status值说明  
        // 200表示成功
        // 202表示请求被接受,但尚未成功
        // 400错误的请求
        // 404文件未找到
        // 500内部服务器错误
        if (XHR.readyState == 4 && XHR.status == 200) {  
            // 这里可以对返回的内容做处理  
            // 一般会返回JSON或XML数据格式  
            console.log(XHR.responseText);  
            // 主动释放,JS本身也会回收的  
            XHR = null;  
        }  
    };  
    XHR.send();  
}  

3.为什么会有同源策略?

同源策略浅谈:只有在浏览器(js)中会有同源策略,若是只通过用户登录进网站,就可以做任何操作,那么浏览器中的js可以获取登陆的cookies,携带这些cookies去访问不同源的网站就可能泄漏用户的信息。

比如,一个用户登录了a网站,那么就会在浏览器上产生cookies,一个坏人做了一个网站b,那个用户不小心点进去b了,b会携带刚才登录的那个cookies去请求用户的其他的信息,或者访问a网站的api做一下敏感的操作。

所以要有同源策略的限制。

什么是同源策略?

  1. 首先来看一下什么是源? 源: 源(origin)就是协议、域名和端口号。
  2. 同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以a.com下的js脚本采用ajax读取b.com里面的文件数据是会报错的。
  3. 不受同源策略限制的:
    1)、页面中的链接,重定向以及表单提交是不会受到同源策略限制的。
    2)、跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的
<script src="..."></script><img><link><iframe>

跨域

既然有了同源策略就正好也去收集一下跨域的知识点。
1. jsonP
2. CORS
3. window.name+iframe
4. window.postMessage()
5. 修改document.domain跨子域
6. WebSocket
jsonp
概念:根据 XmlHttpRequest 对象受到同源策略的影响,而利用 <script>元素的这个开放策略,网页可以得到从其他来源动态产生的JSON数据,而这种使用模式就是所谓的 JSONP。用JSONP抓到的数据并不是JSON,而是任意的JavaScript,用 JavaScript解释器运行而不是用JSON解析器解析

工作原理:就是利用<script>标签没有跨域限制的“漏洞”来达到与第三方通讯的目的。

实现方式:JSONP是一种非正式传输协议,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据(因此叫做json padding ),这样客户端就可以随意定制自
己的函数来自动处理返回数据了基本实例请查看菜鸟教程

缺点:只能发起get请求,不能注册success,error函数,不能确保jsonp的请求成功

CORS(跨域资源共享)

判断两个对象是否相等

首先要认识到,“==”和“===”的区别:

“===”是全等运算符,严格运算符,规则如下:

  1. 不同类型值的做比较,直接返回false.
  2. 同一类型的原始类型值作比较(布尔,数字,字符串),值相等就true,值不等就false
  3. 同一类型的引用类型的值做比较,会比较引用类型的指针(内存地址)是否相同。相同就为true,不同就为false.
  4. undefined和null,不相等
undefined===undefind//true
null===null//true
0===-0//true

“==”相等运算符,相同类型的的数据的比较和“===”一样,不同类型的作比较的时候会自动的做类型转换,再去作比较,有以下几个规则

  1. 原始类型的值中,布尔值和字符串都会转换为数字类型,然后再去比较值是都相同,若相同则true。不同为false;
  2. 对象(这里指的是特别的对象,数值或者函数)和原始类型值比较,对象会转化成原始类型的值比较,var x = 1;
    var obj = {valueOf: function(){ x = 2; return 0 }}
    console.log(obj == 0, x)
    ,这里总结一下,能转化成原始类型的对象就转化成原始类型去比较,不能转化的就直接是false;
  3. undefined和null
undefined==undefined//true
undefined==null//true
null==null//true

有了前面的基础,然后再去看看对象“{ }”的相等的比较。

function isObjectValueEqual(a, b) {

    var aProps = Object.getOwnPropertyNames(a);
    var bProps = Object.getOwnPropertyNames(b);

    // 如果属性的个数不一样就不相等
    if (aProps.length != bProps.length) {
        return false;
    }

    for (var i = 0; i < aProps.length; i++) {
        var propName = aProps[i];

        if (a[propName] !== b[propName]) {
            return false;
        }
    }
    return true;
}

var obj1 = {
    name: "wjq",
    sex : "female"
};

var obj2 = {
    name: "wjq",
    sex : "female"
};

// true
console.log(isObjectValueEqual(obj1, obj2));

对于那些复杂的对象比如属性的值还是一个对象,这个就不适用了
因为js中全是对象,对于两个不知道是什么数据类型的对象的比较如下方法。

function isEqual(a,b){
  //如果a和b本来就全等
  if(a===b){
    //判断是否为0和-0//0===-0为true;
    return  1/a ===1/b;//(a !== 0 || 1/a ===1/b)原来的作者加了这句我觉得这样不对,于是更改了
  }
  //判断是否为null和undefined
  if(a==null||b==null){//这里用的“==”比“===”代码精简了,所以说并不是“===”是最好的选择。
    return a===b;
  }
  //接下来判断a和b的数据类型
  var classNameA=toString.call(a),
    classNameB=toString.call(b);
  //如果数据类型不相等,则返回false
  if(classNameA !== classNameB){
    return false;
  }
  //如果数据类型相等,再根据不同数据类型分别判断
  switch(classNameA){
    case '[object RegExp]':

    case '[object String]':
    //进行字符串转换比较
    return '' + a ==='' + b;
    case '[object Number]':
    //进行数字转换比较,判断是否为NaN
    if(+a !== +a){
      return +b !== +b;
    }
    //判断是否为0或-0
    return +a === 0?1/ +a === 1/b : +a === +b;
    case '[object Date]':
    case '[object Boolean]':
    return +a === +b;
  }
  //如果是对象类型
  if(classNameA == '[object Object]'){
    //获取a和b的属性长度
    var propsA = Object.getOwnPropertyNames(a),
      propsB = Object.getOwnPropertyNames(b);
    if(propsA.length != propsB.length){
      return false;
    }
    for(var i=0;i<propsA.length;i++){
      var propName=propsA[i];
      //如果对应属性对应值不相等,则返回false
      if(a[propName] !== b[propName]){
        return false;
      }
    }
    return true;
  }
  //如果是数组类型
  if(classNameA == '[object Array]'){
    if(a.toString() == b.toString()){
      return true;
    }
    return false;
  }
}