美文网首页
js面试题知识点整理

js面试题知识点整理

作者: 落魂灬 | 来源:发表于2019-11-17 22:44 被阅读0次

    一、js面试题

    1. JavaScript 中的 this 究竟指向谁,箭头函数的 this 有什么不同
    • 普通函数
      this 永远指向调用它的对象,new的时候,指向new出来的对象。
    • 箭头函数
      箭头函数没有自己的 this,当在内部使用了 this时,它会指向最近一层作用域内的 this
    1. 深拷贝和浅拷贝的区别?如何实现?
      两者的区别:一个对象浅复制后,是深层次的对象地址的复制,并没有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会发生改变,而深复制的则是开辟了一个新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
      JSON.stringify与JSON.parse可以实现深拷贝,还可以借用JQ的extend方法。
    • 1.可以递归递归去复制所有层级属性
    
    // 原始对象
    var obj = { 
        a:1, 
        arr: [2,3],
        say:function(){
            console.log('hello')
        },
        obj1:{
            arr:[34,55,5],
            hand:function(){
                console.log('hand')
            },
            obj3:{
                a:1,
                take:function(){
                    console.log('take')
                }
            }
        }
    };
     
    // 开始浅复制
    var shallowObj = shallowCopy(obj);
     
    // 定义浅复制逻辑
    function shallowCopy(src) {
      var dst = {};
      for (var prop in src) {
        if (src.hasOwnProperty(prop)) {
          dst[prop] = src[prop];
        }
      }
      return dst;
    }
     
    // 改变复制后的新对象的属性值(第二层以及更深层次)
    shallowObj.obj1.obj3.take = function(){
        console.log('shallowObj_take') 
    }
    shallowObj.obj1.hand = function(){
        console.log('shallowObj_hand')
    }
     
    // 打印新对象的方法调用
    shallowObj.obj1.obj3.take();  // shallowObj_take
    shallowObj.obj1.hand();      // shallowObj_hand
     
    // 打印原对象的方法调用
    obj.obj1.obj3.take();   // shallowObj_take
    obj.obj1.hand();     // shallowObj_hand
     
    问题出现了:原对象的方法被新对象的修改,而产生变化。
    原因是复制的是对象的地址指针,两个属性共同指向一个对象,只要其一发生变化,另一个也随之变化
    
      1. JSON.stringify与JSON.parse实现深拷贝
    function deepClone(obj){
        let _obj = JSON.stringify(obj),
                objClone = JSON.parse(_obj);
        return objClone
    }    
    let a=[0,1,[2,3],4],
        b=deepClone(a);
    a[0]=1;
    a[2][0]=1;
    console.log(a,b);
    
      1. JQ的extend方法
    let a=[0,1,[2,3],4],
        b=$.extend(true,[],a);
    a[0]=1;
    a[2][0]=1;
    console.log(a,b);
    
    1. js的事件委托是什么,原理是什么?
      事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。用事件委托就可以只用一次dom操作就能完成所有的效果。
    2. 如何判断一个变量是否为数组(isArray)
    1、instanceof
    function isArray (obj) {
      return obj instanceof Array;
    }
    2、Array对象的 isArray方法
    function isArray (obj) {
      return Array.isArray(obj);
    }
    3、Object.prototype.toString
    function isArray (obj) {
      return Object.prototype.toString.call(obj) === '[object Array]';
    }
    
    1. 'DOM2级事件'规定的事件流包含3个阶段:事件捕获,处于目标,事件冒泡
      阻止事件冒泡:event.stopPropagation()
      阻止默认行为:e.preventDefault()

    2. 回调地狱和回调函数
      回调地狱(函数作为参数层层嵌套)
      回调函数(一个函数作为参数需要依赖另一个函数执行调用)

    3. 数组的基本方法
      push和unshift,返回值是length
      pop和shift,返回值是删除的当前项
      slice:抽取当前数组中的一段元素组合成一个新数组。第一个参数从哪里开始,第二个参数是到哪结束
      数组splice第一个参数是索引,第二个参数是想修改或者删除几个元素,第三个是添加的内容
      split把字符串分割成数组
      Array.prototype.includes():判断数组中是否包含某指定的值

    4. 数组去重的方法

    • es6方法:[...new Set(arr)]或者Array.from(new Set(arr))
      forEach + indexOf res.indexOf(val)=== -1,该方法不足之处是NaN进行过滤,改善的方法是使用includes方法
    • filter+indexOf
    • forEach + includes
    • reduce + includes
    • 嵌套循环+splice
    • hash+hasOwnProperty+JSON.stringify
    1. 判断一个变量是不是数组的可靠的方法:
    • Object.prototype.toString.call(list) //[object Array]
    • Array.isArray(list) //true
    1. typeof和instanceof的区别
      typeof返回的类型都是字符串形式
      instanceof,后面一定要是对象类型,并且大小写不能错,该方法适合一些条件选择或分支。

    2. call & apply & bind() 之间的区别:
      call和apply都是改变this指向的方法,区别在于call可以写多个参数,而apply只能写两个参数,第二个参数是一个数组,用于存放要传的参数。
      bind()返回的是一个新函数,必须调用它才会执行

    3. 基本数据类型
      (ES6之前)其中5种为基本类型:string,number,boolean,null,undefined,
      ES6出来的Symbol也是原始数据类型 ,表示独一无二的值
      基本类型的存储方式都是栈存储,引用类型的存储方式都是堆存储

    4. 栈和队列的区别?
      栈的插入和删除操作都是在一端进行的,而队列的操作却是在两端进行的。
      队列先进先出,栈先进后出。
      栈只允许在表尾一端进行插入和删除,而队列只允许在表尾一端进行插入,在表头一端进行删除

    5. 对闭包的理解
      使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在js中,函数即闭包,只有函数才会产生作用域的概念
      闭包有三个特性:
      1.函数嵌套函数
      2.函数内部可以引用外部的参数和变量
      3.参数和变量不会被垃圾回收机制回收

    6. 跨域的解决方案

    • jsonp 只能解决get跨域
      原理:动态创建一个script标签。利用script标签的src属性不受同源策略限制。因为所有的src属性和href属性都不受同源策略限制。可以请求第三方服务器数据内容。
    步骤:
    去创建一个script标签
    script的src属性设置接口地址
    接口参数,必须要带一个自定义函数名 要不然后台无法返回数据。
    通过定义函数名去接收后台返回数据
    //去创建一个script标签
    var script = document.createElement("script");
    //script的src属性设置接口地址 并带一个callback回调函数名称
    script.src = "http://127.0.0.1:8888/index.php?callback=jsonpCallback";
    //插入到页面
    document.head.appendChild(script);
    //通过定义函数名去接收后台返回数据
    function jsonpCallback(data){
    //注意 jsonp返回的数据是json对象可以直接使用
    //ajax 取得数据是json字符串需要转换成json对象才可以使用。
    }
    
    • CORS:跨域资源共享
      原理:服务器设置Access-Control-Allow-OriginHTTP响应头之后,浏览器将会允许跨域请求
      限制:浏览器需要支持HTML5,可以支持POST,PUT等方法兼容ie9以上
      需要后台设置
      Access-Control-Allow-Origin: * //允许所有域名访问,或者 Access-Control-Allow-Origin: http://a.com //只允许所有域名访问

    二、vue面试题

    1. route 和router 的区别
    • router为VueRouter的实例,相当于一个全局的路由器对象,里面含有很多属性和子对象,例如history对象,经常用的跳转链接就可以用this.$router.push,和router-link跳转一样。
    • route相当于当前正在跳转的路由对象。。可以从里面获取name,path,params,query等。
    1. Vue的双向数据绑定原理是什么?
      vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
    2. <keep-alive></keep-alive>的作用是什么?
      <keep-alive></keep-alive> 包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。

    相关文章

      网友评论

          本文标题:js面试题知识点整理

          本文链接:https://www.haomeiwen.com/subject/tnpmictx.html