indexeddb:在请求期间更改变量名称如何导致错误?

indexeddb: How does changing the variable names during a request cause one to error?

我正在学习 indexeddb,在比较下面的 2 个函数时我感到困惑。它们是相同的,只是我将代码#2 的最后一个 request 变量名称更改为变量 request2 名称。这导致它们产生不同的结果。

代码#1

function updateEntry(){
    var tx = db.transaction('practiceStore', 'readwrite');
    var store = tx.objectStore('practiceStore');
    var request = store.get(3);
    request.onsuccess = event => {
        console.log(request.result)
        let entry = request.result;
        
        entry.title = 'mdn way'
        var request = store.put(entry)
        request.onsuccess = event => {
            console.log('putting')
        }
    }
    tx.oncomplete = event => {
        console.log('tx complete')
    }
}

输出:

errors

对比

代码#2

function updateEntry(){
    var tx = db.transaction('practiceStore', 'readwrite');
    var store = tx.objectStore('practiceStore');
    var request = store.get(3);
    request.onsuccess = event => {
        console.log(request.result)
        let entry = request.result;
        
        entry.title = 'mdn way'
        var request2 = store.put(entry)
        request2.onsuccess = event => {
            console.log('putting')
        }
    }
    tx.oncomplete = event => {
        console.log('tx complete')
    }
}

产出

//does expected behavior

console.log(request.result) 行上的代码#1 错误。我尝试使用 chrome devtools 调试器,发现调试器从未进入 var request = store.put(entry),这让我更加困惑。

代码#1 错误,因为请求未定义。我在概念上不明白稍后重新定义 request 会如何改变任何东西。感谢任何帮助,谢谢。

有趣的是,我认为这与 javascript 中称为“提升”的东西有关。

基本上,提升意味着代码中的变量声明被“带到代码的顶部”。在声明和初始化变量的情况下,就像您对 var request = store.put(entry) 所做的那样,声明 (var request;) 被提升到顶部而不是初始化(实际上分配 store.put 的结果)。

因此,当 运行 您的代码#1 实际上看起来像这样时:

request.onsuccess = event => {
        var request; //this is the "hoisting" I am referring to
        console.log(request.result) //this is currently undefined now!
        let entry = request.result;
        
        entry.title = 'mdn way'
        request = store.put(entry) //this is the assignment
        request.onsuccess = event => {
            console.log('putting')
        }
    }

这有点令人困惑,但这里解释得很好 (https://www.w3schools.com/js/js_hoisting.asp),尤其是关于提升声明而不是初始化的部分(参见 link 中的示例 2)。

当您将名称更改为 request2 时,它同样会被提升,但不会覆盖外部请求,因此 request.result 并非未定义。

这有意义吗?