2020 祝安,缝隙中寻找机遇:面试题第四波:JS

320 阅读3分钟

非常感谢,前同事行长@onlyadaydreamer分享的面经。

其实每次与产品同学的争论都是无意义的,因为我们始终怼不过她们😭😭😭

不过还好,中午打游戏的时候,公司5V5,把UI和产品杀穿了,😤😤😤

继续正文

前端xss攻击和防御

前端xss攻击和防御 欢迎点击收藏 👏 👏 👏

jquery.ready方法实现原理

if ( document.readyState === "complete" ) {
      // Handle it asynchronously to allow scripts the opportunity to delay ready
      //这里的setTimeout是为了异步
      setTimeout( jQuery.ready, 1 );

    // Standards-based browsers support DOMContentLoaded
    //标准浏览器侦听事件接口:document.addEventListener
    } else if ( document.addEventListener ) {
      // Use the handy event callback
      document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

      // A fallback to window.onload, that will always work
      //文章一开始说了,这里为了保证一定会触发ready,所以还针对onload也绑定一次回调
      window.addEventListener( "load", jQuery.ready, false );

    // If IE event model is used
    } else {
      //IE侦听事件接口:document.attachEvent
      //如果有onreadystatechange事件,侦听之
      // Ensure firing before onload, maybe late but safe also for iframes
      document.attachEvent( "onreadystatechange", DOMContentLoaded );

      // A fallback to window.onload, that will always work
      window.attachEvent( "onload", jQuery.ready );


      // http://javascript.nwbox.com/IEContentLoaded/
      // 见下边说明
      // If IE and not a frame
      // continually check to see if the document is ready
      var top = false;

      try {
        top = window.frameElement == null && document.documentElement;
      } catch(e) {}

      //如果是IE并且不是iframe
      if ( top && top.doScroll ) {
        (function doScrollCheck() {
          if ( !jQuery.isReady ) {

            try {
              // Use the trick by Diego Perini
              // http://javascript.nwbox.com/IEContentLoaded/
              //一直调用doScroll滚动,因为DOM渲染结束前,DOM节点是没有doScroll方法的,所以一直会异常
              //直到DOM渲染结束了,这个时候doScroll方法不会抛出异常,然后就调用$.ready()
              top.doScroll("left");
            } catch(e) {
              return setTimeout( doScrollCheck, 50 );
            }

            // and execute any waiting functions
            jQuery.ready();
          }
        })();
      }
    }

知道Symbol吗?有什么作用?

根据规范,对象的属性键只能是字符串类型或者 Symbol 类型。不是 Number,也不是 Boolean,只有字符串或 Symbol 这两种类型。

Symbol 保证是唯一的。即使我们创建了许多具有相同描述的 Symbol,它们的值也是不同。描述只是一个标签,不影响任何东西。

例如,这里有两个描述相同的 Symbol —— 它们不相等:

let id1 = Symbol("id");
let id2 = Symbol("id");

alert(id1 == id2); // false

注意:Symbol 不会被自动转换为字符串

JavaScript 中的大多数值都支持字符串的隐式转换。例如,我们可以 alert 任何值,都可以生效。Symbol 比较特殊,它不会被自动转换 。 例如,这个 alert 将会提示出错:

let id = Symbol("id");
alert(id); // 类型错误:无法将 Symbol 值转换为字符串。

复制代码这是一种防止混乱的“语言保护”,因为字符串和 Symbol 有本质上的不同,不应该意外地将它们转换成另一个。

如果我们真的想显示一个 Symbol,我们需要在它上面调用 .toString(),如下所示:

let id = Symbol("id");
alert(id.toString()); // Symbol(id),现在它有效了

复制代码或者获取 symbol.description 属性,只显示描述(description):

let id = Symbol("id");
alert(id.description); // id

Symbol 允许我们创建对象的“隐藏”属性,代码的任何其他部分都不能意外访问或重写这些属性。

例如,如果我们使用的是属于第三方代码的 user 对象,我们想要给它们添加一些标识符。

我们可以给它们使用 Symbol 键:

let user = { // 属于另一个代码
  name: "John"
};

let id = Symbol("id");

user[id] = 1;

alert( user[id] ); // 我们可以使用 Symbol 作为键来访问数据

手写一个ajax

    function get(url,data,callback){

        let paramArr = [];
        let encodeData;
        if (data instanceof Object) {
            for (let key in data) {
                // 参数拼接需要通过 encodeURIComponent 进行编码
                paramArr.push( encodeURIComponent(key) + '=' + encodeURIComponent(data[key]) )
            }
            encodeData = paramArr.join('&')
        }
        url += encodeData;
        
        var xhr; 
        if (window.XMLHttpRequest) {
            xhr = new XMLHttpRequest();
        } else {
            //如果是IE5或者IE6浏览器,则使用ActiveX对象
            xhr = ActiveXObject("Microsoft.XMLHTTP");
        }

        xhr.open('GET',url,true)

        xhr.onreadystatechange = function(){

            if(xhr.readyState === 4 && xhr.status == 200 || xhr.status == 304){
                callback(response)
            }
        }

        xhr.send(null)
    }

    function post(url,data,callback){
        var xhr; 
        if (window.XMLHttpRequest) {
            xhr = new XMLHttpRequest();
        } else {
            //如果是IE5或者IE6浏览器,则使用ActiveX对象
            xhr = ActiveXObject("Microsoft.XMLHTTP");
        }
        xhr.open('POST',url,true)
        
        xhr.setRequestHeader('Content-Type':"application/x-www-form-urlencoded")
        
        xhr.onreadystatechange = function(){
            if(xhr.readyState === 4 && xhr.status === 200 || xhr.status === 304){
                callback(response)
            }
        }
        xhr.send(data)
    }

深拷贝和浅拷贝

可以参考我的这个文档深拷贝和浅拷贝