Object.keys(obj) 与 Reflect.ownKeys(obj) 获取 对象 keys
浅比较
只比较对象的第一级,第一级以下,深层不进行比较
1 2 3 4 5 6 7
|
function isObj(obj) { return obj !== null && /^object|function$/.test(typeof obj) }
|
flowchart LR
start((开始)) --> step1{"isObj比较"}
step1 -->|是| step2{"===比较"}
step2 -->|是| step3{"keys.length比较"}
step3 -->|是| step4{"是否存在相同的key\n值是否相等"}
step4 -->|是| res1[浅比较相同]
step4 -->|否| res[不是同一对象]
step3 -->|否| res
step2 -->|否| res
step1 -->|否| res
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
function shallowEqual(obj1, obj2) { if(!isObj(obj1) || !isObj(obj2)) return false if(obj1 === obj2) return true let obj1Keys = Reflect.ownKeys(obj1), obj2Keys = Reflect.ownKeys(obj2) if(obj1Keys.length !== obj2Keys.length) return false for (var i=0; i<obj1Keys.length; i++) { let element = obj1Keys[i] console.log(element, !obj2.hasOwnProperty(element) , !Object.is(obj1[element], obj2[element])) if(!obj2.hasOwnProperty(element) || !Object.is(obj1[element], obj2[element])) return false } return true }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
let obj1, obj2 let obj = { a: 'a' }
obj1 = { x: 'obj', obj: obj, } console.log(obj1.obj, 'obj1')
let o = obj obj2 = { x: 'obj', obj: o } obj2.obj.ccc = 111 console.log(obj2.obj, 'obj2')
console.log(shallowEqual(obj1, obj2))
|
obj2.obj 与 obj1.obj 具有相同的 key,值都是对象类型,虽然引用地址不同,但因为只作了第一级只比较,所以浅比较认为他们是相同的对象。
React.Component 与 React.PureComponent 的区别
PureComponent 会给类组件默认加一个 shouldComponentUpdate 周期函数,在该生命周期中,会对新老属性、状态做浅比较,比较结果返回 false,视图不会更新。
如 Demo
1 2 3 4 5 6 7
| addBox = () => { let {boxs} = this.state boxs.push(4) this.setState({ boxs }) }
|
通过 setState ,boxs 会被认为是相同的引用地址。shouldComponentUpdate,同一个 boxs 引用地址不变,shouldComponentUpdate 返回 false 不能实现视图更新
1 2 3 4
| addBox = () => { this.state.boxs.push(4) this.forceUpdate() }
|
采用 this.forceUpdate 跳过 shouldComponentUpdate 检验,实现视图更新
1 2 3 4 5
| addBtn = () => { const {boxs} = this.state boxs.push(4) this.setState({boxs: [...boxs]}) }
|
this.setState({boxs: [...boxs]})
通过解构,定义一个同样值的新数组,作为对象属性 boxs 的值,数组虽然值相同,但引用地址不同。shouldComponentUpdate 校验返回 true,实现了视图更新