美文网首页
React源码细节--Component, PureCompon

React源码细节--Component, PureCompon

作者: 原型设计 | 来源:发表于2019-11-19 14:11 被阅读0次

用了很久的react了,突然想一探究竟react源码什么样子,于是开始了我的react源码细节之路探索,我这里不讲源码,只讲我对知识点的扩展和联想,希望对大家有用。

首先,看看平时我们继承的 Component 和 PureComponent。

Component 和 PureComponent

首先我们会看到这句话:

路径:react/packages/react/src/ReactBaseClasses.js /

const emptyObject = {};
if (__DEV__) {
  Object.freeze(emptyObject);
}

于是MDN 了 Object.freeze(),MDN这样解释的:Object.freeze()方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。

这里冻结了一个emptyObject属性,我联想了const 也可以定义常量,引发了我的思考?

Object.freeze() 与 const name = 'lq' 区别;

const: 无法重新分配变量,但仍然可以改变对象本身(说的很简单,需要大家自己理解)。

Object.freeze(): 对象具有无法修改或删除的属性。实际上具有嵌套属性的对象并未被冻结(说的很简单,需要大家自己理解)。

那如何封装一个深度冻结对象呢?

封装一个深度冻结对象

module.exports = function deepFreeze (o) {
  Object.freeze(o);

  Object.getOwnPropertyNames(o).forEach(function (prop) {
    if (o.hasOwnProperty(prop)
    && o[prop] !== null
    && (typeof o[prop] === "object" || typeof o[prop] === "function")
    && !Object.isFrozen(o[prop])) {
      deepFreeze(o[prop]);
    }
  });
  
  return o;
};

这个方法里面有三个方法引发了探索和思考:

Object.getOwnPropertyNames()
Object.prototype.hasOwnProperty()
Object.isFrozen()

Object.getOwnPropertyNames()

MDN: Object.getOwnPropertyNames(obj: 其自身的可枚举和不可枚举属性的名称被返回) 方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。

如何只获取可枚举属性:

function ParentClass() {}
ParentClass.prototype.inheritedMethod = function() {};

function ChildClass() {
  this.prop = 5;
  this.method = function() {};
}

ChildClass.prototype = new ParentClass;
ChildClass.prototype.prototypeMethod = function() {};

console.log(
  Object.getOwnPropertyNames(
    new ChildClass()  // ["prop", "method"]
  )
);

只获取不可枚举的属性:

var target = myObject;
var enum_and_nonenum = Object.getOwnPropertyNames(target);
var enum_only = Object.keys(target);
var nonenum_only = enum_and_nonenum.filter(function(key) {
    var indexInEnum = enum_only.indexOf(key);
    if (indexInEnum == -1) {
        // 没有发现在enum_only健集中意味着这个健是不可枚举的,
        // 因此返回true 以便让它保持在过滤结果中
        return true;
    } else {
        return false;
    }
});

Object.prototype.hasOwnProperty()

MDN: hasOwnProperty(str:要检测的属性的 String 字符串形式表示的名称,或者 Symbol。) 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。

Object.isFrozen()

Object.isFrozen()方法判断一个对象是否被冻结。

继续往后看

function Component(props, context, updater) {
  this.props = props;
  this.context = context;
  // If a component has string refs, we will assign a different object later.
  this.refs = emptyObject;
  // We initialize the default updater but the real one gets injected by the
  // renderer.
  this.updater = updater || ReactNoopUpdateQueue;
}

Component.prototype.isReactComponent = {};

Component.prototype.setState = function(partialState, callback) {
  invariant(
    typeof partialState === 'object' ||
      typeof partialState === 'function' ||
      partialState == null,
    'setState(...): takes an object of state variables to update or a ' +
      'function which returns an object of state variables.',
  );
  this.updater.enqueueSetState(this, partialState, callback, 'setState');
};


Component.prototype.forceUpdate = function(callback) {
  this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};


// 为什么需要多一个中间函数?寄生继承
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;


function PureComponent(props, context, updater) {
  this.props = props;
  this.context = context;
  // If a component has string refs, we will assign a different object later.
  this.refs = emptyObject;
  this.updater = updater || ReactNoopUpdateQueue;
}

// 寄生虫
const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
pureComponentPrototype.constructor = PureComponent;

// 1.这句话为什么不可以写在 PureComponent.prototype = new  ComponentDummy()前面,有什么影响,因为前面PureComponent.prototype是引用类型。
// 2.性能:减少原型链查找以及扩展自身原型上面的方法。
// Avoid an extra prototype jump for these methods.
Object.assign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent = true;

export {Component, PureComponent};

这里为什么使用寄生继承?我们知道JavaScript继承方式有很多种,为什么react要这样实现继承?相比较其他的继承方式优势在哪里?希望大家下来多多思考。

相关文章

网友评论

      本文标题:React源码细节--Component, PureCompon

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