history.state 总是和 popstate event.state 一样吗?
Is history.state always the same as popstate event.state?
history.state
是否总是与 popstate event.state
相同?
window.addEventListener("popstate", function (event){
console.log(history.state === event.state); // ALWAYS TRUE
// IT SEEMS
}, false);
如果是,为什么两次拥有同样的东西。
不,它们并不总是相同的。
来自MDN
The popstate
event is fired when the active history entry changes. If the history entry being activated was created by a call to history.pushState()
or was affected by a call to history.replaceState()
, the popstate
event's state property contains a copy of the history entry's state object.
Note that just calling history.pushState()
or history.replaceState()
won't trigger a popstate
event. The popstate
event will be triggered by doing a browser action such as a click on the back or forward button (or calling history.back()
or history.forward()
in JavaScript).
以下代码示例表明它们可以不同 (Google Chrome - Version 63.0.3239.108
):
请注意: FireFox
存在一些问题。
window.onpopstate = function(event) {
console.log(event.state === history.state);
};
history.pushState({page: 1}, "title 1", "?page=1");
history.pushState({page: 2}, "title 2", "?page=2");
history.replaceState({page: 3}, "title 3", "?page=3");
history.back();
history.back();
history.go(2);
是的,它们应该始终代表相同的状态。
根据 the specs 当请求浏览器执行历史遍历时,
- Set
history.state
to state.
其中 state 与 16.1
中的相同
- If state changed is true, then fire an event named
popstate
at the Document
object's Window
object, using PopStateEvent
, with the bubbles attribute initialized to true and the state
attribute initialized state.
强调我的
另一个答案的代码证明 Google Chrome 不是 return 同一个对象,而是一个副本。
然而,这两个状态是相同的,而且 UA 似乎不必尊重这个状态对象上的 [SameObject] 策略。
所以为了检查相等性,应该检查状态对象的内容,而不是使用直接相等性检查。
window.onpopstate = function(event) {
console.log('same state',
JSON.stringify(event.state) === JSON.stringify(history.state) // always true
);
};
const obj1 = {page: 1};
history.pushState(obj1, "title 1", "?page=1");
console.log('[SameObject]', history.state === obj1); // false
console.log(history.state); // {page: 1}
history.pushState({page: 2}, "title 2", "?page=2");
history.replaceState({page: 3}, "title 3", "?page=3");
history.back();
history.back();
history.go(2);
至于为什么把它设置在两个不同的地方,我不得不承认我没有一个可靠的答案...
history.state
是否总是与 popstate event.state
相同?
window.addEventListener("popstate", function (event){
console.log(history.state === event.state); // ALWAYS TRUE
// IT SEEMS
}, false);
如果是,为什么两次拥有同样的东西。
不,它们并不总是相同的。
来自MDN
The
popstate
event is fired when the active history entry changes. If the history entry being activated was created by a call tohistory.pushState()
or was affected by a call tohistory.replaceState()
, thepopstate
event's state property contains a copy of the history entry's state object.Note that just calling
history.pushState()
orhistory.replaceState()
won't trigger apopstate
event. Thepopstate
event will be triggered by doing a browser action such as a click on the back or forward button (or callinghistory.back()
orhistory.forward()
in JavaScript).
以下代码示例表明它们可以不同 (Google Chrome - Version 63.0.3239.108
):
请注意: FireFox
存在一些问题。
window.onpopstate = function(event) {
console.log(event.state === history.state);
};
history.pushState({page: 1}, "title 1", "?page=1");
history.pushState({page: 2}, "title 2", "?page=2");
history.replaceState({page: 3}, "title 3", "?page=3");
history.back();
history.back();
history.go(2);
是的,它们应该始终代表相同的状态。
根据 the specs 当请求浏览器执行历史遍历时,
- Set
history.state
to state.
其中 state 与 16.1
中的相同
- If state changed is true, then fire an event named
popstate
at theDocument
object'sWindow
object, usingPopStateEvent
, with the bubbles attribute initialized to true and thestate
attribute initialized state.
强调我的
另一个答案的代码证明 Google Chrome 不是 return 同一个对象,而是一个副本。
然而,这两个状态是相同的,而且 UA 似乎不必尊重这个状态对象上的 [SameObject] 策略。
所以为了检查相等性,应该检查状态对象的内容,而不是使用直接相等性检查。
window.onpopstate = function(event) {
console.log('same state',
JSON.stringify(event.state) === JSON.stringify(history.state) // always true
);
};
const obj1 = {page: 1};
history.pushState(obj1, "title 1", "?page=1");
console.log('[SameObject]', history.state === obj1); // false
console.log(history.state); // {page: 1}
history.pushState({page: 2}, "title 2", "?page=2");
history.replaceState({page: 3}, "title 3", "?page=3");
history.back();
history.back();
history.go(2);
至于为什么把它设置在两个不同的地方,我不得不承认我没有一个可靠的答案...