美文网首页
JS面试总结

JS面试总结

作者: lceCola | 来源:发表于2019-02-15 17:10 被阅读0次

    组件载入阶段:

    componentWillMount:组件即将被装载、渲染到页面上,只调用1次
    componentDidMount:组件真正在被装载之后,这里可以拿到真实DOM执行操作,只调用1次

    运行中状态:

    componentWillReceiveProps(nextProps):组件将要接收到新属性的时候调用,在这时setState不会触发额外的render,因为此时已经有一次来自父组件引发的render了。
    shouldComponentUpdate:组件接受到新属性或者新状态的时候(返回 false,接收数据后不更新,阻止 render ,后面的函数不会继续执行)
    componentWillUpdate:组件即将更新不能修改属性和状态
    componentDidUpdate:组件已经更新

    销毁阶段:

    componentWillUnmount:组件即将销毁,这时候可以销毁绑定的事件监听或者定时器什么的。

    render

    render:组件在这里生成虚拟的 DOM 节点

    React中的props和state的用法

    sate 是一种数据结构,用于组件挂载时所需数据的默认值。state 可能会随着时间的推移而发生突变,但多数时候是作为用户事件行为的结果。
    Props则是组件的配置。props 由父组件传递给子组件,并且就子组件而言,props 是不可变的(immutable)。

    React如何性能优化

    1. 充分利用shouldComponentUpdate函数,不过这需要你的组件尽量最小化,如果当前组件数据过于复杂,其实是很难优化的。
    2. 给你的DOM遍历上加上唯一的key,注意尽量不要用index,因为如果你新DOM中删了某一个节点,它会重新排列index,那跟原来同层级一比就都会完全不一样,而重新渲染了,所以最好使用id值什么的作key值。
    3. 能用const声明的就用const。
    4. DOM里少用箭头函数,当然其实要传参时也还是得用。再者,函数bind尽量写在constructor,避免每次render重新bind。
    5. 减少对真实DOM的操作。
    6. 如果是用webpack搭建环境的话,当一个包过大加载过慢时,可分打成多个包来优化。
    

    react与vue的对比

    相同点:
    1、都用虚拟DOM实现快速渲染
    2、我觉得父子,兄弟通信这些都挺像的,也都有自己的状态管理器:react=>redux, vue=>vuex
    3、都是轻量级框架
    4、 现在vue也在渐渐吸收react中的一些语法,比如JSX语法,类式声明写法等
    不同点:
    1、 React属于单向数据流——MVC模式,vue则属于双向——MVVM模式。
    2、 react兼容性比vue好,vue不兼容IE8。
    3、react采用JSX语法,vue采用的则是html模板语法。
    4、vue的css可以有组件的私有作用域,react则没有。
    5、react比vue好的另一点是,它是团队维护,而vue属于个人,一般来说,大型项目更倾向于react,小型则用vue,当然这也不是绝对。

    继承

    定义一个父类

    // 定义一个动物类
    function Animal (name) {
      // 属性
      this.name = name || 'Animal';
      // 实例方法
      this.sleep = function(){
        console.log(this.name + '正在睡觉!');
      }
    }
    // 原型方法
    Animal.prototype.eat = function(food) {
      console.log(this.name + '正在吃:' + food);
    };
    

    1、原型链继承 核心: 将父类的实例作为子类的原型

    function Cat(){ 
    }
    Cat.prototype = new Animal();
    Cat.prototype.name = 'cat';
    
    // Test Code
    var cat = new Cat();
    console.log(cat.name);
    console.log(cat.eat('fish'));
    console.log(cat.sleep());
    console.log(cat instanceof Animal); //true 
    console.log(cat instanceof Cat); //true
    

    2、构造继承 核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类

    function Cat(name){
      Animal.call(this);
      this.name = name || 'Tom';
    }
    
    // Test Code
    var cat = new Cat();
    console.log(cat.name);
    console.log(cat.sleep());
    console.log(cat instanceof Animal); // false
    console.log(cat instanceof Cat); // true
    

    3、实例继承 核心:为父类实例添加新特性,作为子类实例返回

    function Cat(name){
      var instance = new Animal();
      instance.name = name || 'Tom';
      return instance;
    }
    
    // Test Code
    var cat = new Cat();
    console.log(cat.name);
    console.log(cat.sleep());
    console.log(cat instanceof Animal); // true
    console.log(cat instanceof Cat); // false
    

    4、拷贝继承

    function Cat(name){
      var animal = new Animal();
      for(var p in animal){
        Cat.prototype[p] = animal[p];
      }
      Cat.prototype.name = name || 'Tom';
    }
    
    // Test Code
    var cat = new Cat();
    console.log(cat.name);
    console.log(cat.sleep());
    console.log(cat instanceof Animal); // false
    console.log(cat instanceof Cat); // true
    

    更多继承方法

    原型和原型链

    在 JavaScript 中,每当定义一个对象(函数也是对象)时候,对象中都会包含一些预定义的属性。其中每个函数对象都有一个prototype 属性,这个属性指向函数的原型对象。
    原型对象,顾名思义,它就是一个普通对象。从现在开始你要牢牢记住原型对象就是 Object.prototype

    原型链示意图

    使用原型扩展提高性能

    可能很多人会无法理解为什么我们要通过prototype来输入方法,也听过看过很多人说直接使用函数的效率是最低的,但是不知道原理。其实我们拿上面的案例做个简单的实验你或许就能懂了:

    var Cat = function(){
        this.Color = "black";
        this.Eat = function(){
            alert("吃老鼠");
        };
    }
    Cat.prototype.A = function(){
        alert("Cat A");
    };
    Cat.prototype.B =  function(){
        alert("Cat B");
    }
    var cat1 = new Cat();
    var cat2 = new Cat();
    alert(cat1.Eat == cat2.Eat) // false
    alert(cat1.A == cat2.A) // true
    

    PS:看到结果是否很震惊,Eat和A方法都是Cat对象里面的,为什么两个实例一对比会产生不同的结果呢?在JS原型链中,通过prototype声明的方法会被存入内存中,不管我们实例化多少次Cat访问通过prototype扩展的A或者B方法,他们都是去读取同一个内存,但是Cat自身的属性和方法却不是这样,而是每次都会跟着实例化,如果该对象被频繁调用,那将会占用大量的内存,这就是为什么我们用prototype来扩展我们对象的属性和方法。

    null和undefined的区别

    null: Null类型,代表“空值”,代表一个空对象指针,使用typeof运算得到 “object”,所以你可以认为它是一个特殊的对象值。
    undefined: Undefined类型,当一个声明了一个变量未初始化时,得到的就是undefined。

    闭包

    闭包就是能够读取其他函数内部变量的函数,闭包就是将函数内部和函数外部连接起来的一座桥梁。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。

    function f1(){
        var n=999;
        function f2(){
          alert(n); 
        }
        return f2;
      }
      var result=f1();
      result(); // 999
    

    优缺点

    缺点:
    1、由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
    2、闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

    相关文章

      网友评论

          本文标题:JS面试总结

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