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

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;
  }
}

猜你喜欢

转载自blog.csdn.net/o_xiaopingguo/article/details/80407801