Aja*_*aur 74 javascript reactjs
在React的这个文档中,据说
shallowCompare对当前props和nextProps对象以及当前state和nextState对象执行浅等式检查.
我无法理解的事情是If It浅层比较对象,那么shouldComponentUpdate方法将始终返回true,如
我们不应该改变国家.
如果我们没有改变状态,那么比较将始终返回false,因此shouldComponent更新将始终返回true.我很困惑它是如何工作的,我们将如何覆盖它以提高性能.
And*_*yco 107
浅比较检查是否平等.比较标量值(数字,字符串)时,它会比较它们的值.比较对象时,它不会比较它们的属性 - 只比较它们的引用(例如"它们是否指向同一个对象?").
让我们考虑一下user对象的形状
user = {
name: "John",
surname: "Doe"
}
Run Code Online (Sandbox Code Playgroud)
例1:
const user = this.state.user;
user.name = "Jane";
console.log(user === this.state.user); // true
Run Code Online (Sandbox Code Playgroud)
请注意您更改了用户名.即使有这种变化,对象也是相同的.他们的参考完全相同.
例2:
const user = clone(this.state.user);
console.log(user === this.state.user); // false
Run Code Online (Sandbox Code Playgroud)
现在,对对象属性没有任何改变,它们完全不同.通过克隆原始对象,您可以创建具有不同引用的新副本.
克隆函数可能看起来像这样(ES6语法)
const clone = obj => Object.assign({}, ...obj);
Run Code Online (Sandbox Code Playgroud)
浅比较是检测变化的有效方法.它希望你不要改变数据.
sup*_*upi 18
浅层比较是指所比较的对象的属性是使用"==="或严格相等来完成的,并且不会对属性进行更深入的比较.例如
// a simple implementation of the shallowCompare.
// only compares the first level properties and hence shallow.
// state updates(theoretically) if this function returns true.
function shallowCompare(newObj, prevObj){
for (key in newObj){
if(newObj[key] !== prevObj[key]) return true;
}
return false;
}
//
var game_item = {
game: "football",
first_world_cup: "1930",
teams: {
North_America: 1,
South_America: 4,
Europe: 8
}
}
// Case 1:
// if this be the object passed to setState
var updated_game_item1 = {
game: "football",
first_world_cup: "1930",
teams: {
North_America: 1,
South_America: 4,
Europe: 8
}
}
shallowCompare(updated_game_item1, game_item); // true - meaning the state
// will update.
Run Code Online (Sandbox Code Playgroud)
虽然两个对象看起来都是一样的,game_item.teams但引用的不一样updated_game_item.teams.要使两个对象相同,它们应指向同一个对象.因此,这导致被评估的状态被更新
// Case 2:
// if this be the object passed to setState
var updated_game_item2 = {
game: "football",
first_world_cup: "1930",
teams: game_item.teams
}
shallowCompare(updated_game_item2, game_item); // false - meaning the state
// will not update.
Run Code Online (Sandbox Code Playgroud)
这次,每个属性都返回true进行严格比较,因为新旧对象中的teams属性指向同一个对象.
// Case 3:
// if this be the object passed to setState
var updated_game_item3 = {
first_world_cup: 1930
}
shallowCompare(updated_game_item3, game_item); // true - will update
Run Code Online (Sandbox Code Playgroud)
该updated_game_item3.first_world_cup属性未通过严格评估,因为1930是数字而game_item.first_world_cup字符串.如果比较松散(==),这将会过去.尽管如此,这也将导致状态更新.
补充说明:
在React中还有浅析比较的遗留解释:
shallowCompare对当前props和nextProps对象以及当前state和nextState对象执行浅等式检查.
它通过迭代被比较的对象的键来实现这一点,并且当每个对象中的键的值不严格相等时返回true.
UPD:当前的文档说浅浅的比较:
如果React组件的render()函数在给定相同的props和state的情况下呈现相同的结果,则在某些情况下可以使用React.PureComponent来提高性能.
React.PureComponent的shouldComponentUpdate()只是浅浅地比较对象.如果这些包含复杂的数据结构,则可能会产生更深层次差异的假阴性.只有当你希望有简单的道具和状态时才扩展PureComponent,或者当你知道深层数据结构已经改变时使用forceUpdate()
UPD2:我认为和解也是浅析比较理解的重要主题.
小智 7
对于某些人来说,接受的答案可能有点误导。
user = {
name: "John",
surname: "Doe"
}
const user = this.state.user;
user.name = "Jane";
console.log(user === this.state.user); // true
Run Code Online (Sandbox Code Playgroud)
该语句特别是“注意您更改了用户名。即使进行此更改,对象也是相等的。它们的引用完全相同。”
当您对 javascript 中的对象执行以下操作时:
const a = {name: "John"};
const b = a;
Run Code Online (Sandbox Code Playgroud)
改变两个变量中的任何一个都会改变它们,因为它们具有相同的引用。这就是为什么它们总是==, ===, Object.is()彼此相等 ( ) 的原因。
现在对于React,以下是浅层比较函数: https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/shallowEqual.js
/**
* Performs equality by iterating through keys on an object and returning false
* when any key has values which are not strictly equal between the arguments.
* Returns true when the values of all keys are strictly equal.
*/
function shallowEqual(objA: mixed, objB: mixed): boolean {
if (is(objA, objB)) {
return true;
}
if (typeof objA !== 'object' || objA === null ||
typeof objB !== 'object' || objB === null) {
return false;
}
const keysA = Object.keys(objA);
const keysB = Object.keys(objB);
if (keysA.length !== keysB.length) {
return false;
}
// Test for A's keys different from B.
for (let i = 0; i < keysA.length; i++) {
if (
!hasOwnProperty.call(objB, keysA[i]) ||
!is(objA[keysA[i]], objB[keysA[i]])
) {
return false;
}
}
return
Run Code Online (Sandbox Code Playgroud)
对于非基元(对象),它检查:
Object.is())第二个对象。Object.is())第二个对象中的键值对。这是针对第一级密钥完成的。如果该对象的键的值是另一个对象,则此函数不会检查该对象深度的相等性。我花了一段时间才真正知道shallow compare和===是两个不同的东西,特别是在阅读下面的 redux 文档时。
但是,当将操作分派到 Redux 存储时,useSelector() 仅在选择器结果与最后结果不同时强制重新渲染。从 v7.1.0-alpha.5 开始,默认比较是严格的 === 引用比较。这与 connect() 不同,后者对 mapState 调用的结果使用浅层相等检查来确定是否需要重新渲染。这对您应该如何使用 useSelector() 有几个影响。
所以一步一步地,严格相等===是由Javascript语言非常一致地定义的,https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality
它的作用是,如果两个项是原始项,则按值进行比较;如果它们是对象,则按引用进行比较。当然,如果两个对象的类型不同,它们将永远不会匹配。
浅层可能不是该语言的内置功能。这里的几个答案向我们指出了实现的一些变化,https://github.com/facebook/fbjs/blob/main/packages/fbjs/src/core/shallowEqual.js
这个想法是通过值比较两个项目(如果它们是原始的)。但对于非基元,我们降低一级。对于对象来说,如果两个对象的键不同,我们就说它们不相同。如果某个键下的值不同,我们说它们也不相同。
这意味着,浅比较检查比严格 equal 更多===,特别是当涉及到对象时。快速浏览一下可能会表明,===不需要做太多猜测工作。
| 归档时间: |
|
| 查看次数: |
40612 次 |
| 最近记录: |