JS面试总结

组件载入阶段:

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),这时一定要小心,不要随便改变父函数内部变量的值。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。