let聲明的全局變量不是window對象屬性


今天在控制台寫刪除數組第一個元素的代碼時,發現了一個問題,以下是書中源碼,

let arr = [1,2,3,4,5]
Array.prototype.reIndex = function (myArray) {
    const newArray = [];
    for (let i=0; i<myArray.length; i++)  {
        if (myArray[i] !== undefined) {
              newArray.push(myArray[i]);
        }
    }
    return newArray;
}    
Array.prototype.removeFirPos = function () {
    for (let i=0;i<this.length;i++){
         this[i] = this[i+1]
    }
    return this.reIndex(this)
}

arr = arr.removeFirPos()


console.log(arr)//控制台輸出

按這個源碼,我進行了更改,使用了箭頭函數,如下

let arr = [1,2,3,4,5]
Array.prototype.reIndex = (myArray) => {
    const newArray = [];
    for (let i=0; i<myArray.length; i++)  {
        if (myArray[i] !== undefined) {
              newArray.push(myArray[i]);
        }
    }
    return newArray;
}    
Array.prototype.removeFirPos = () => {
    for (let i=0;i<this.length;i++){
         this[i] = this[i+1]
    }
    return this.reIndex(this)
}

arr = arr.removeFirPos()


console.log(arr)//控制台輸出

然后發現報錯,typeerror:this.reIndex is not a function。查找下發現箭頭函數沒有自己的this。

我又想了一下,變量arr調用方法removeFirPos(),那么這個this不就是指向了arr嗎,后來一想。。。這不是非箭頭函數時候的指向嘛

然后繼續網絡查找找到了一句話:由於箭頭函數不綁定this, 它會捕獲其所在(即定義的位置)上下文的this值, 作為自己的this值

所有this的指向在非嚴格模式下是window。為了更好的理解我編寫以下代碼

function Test1() {
    console.log(this);
    setTimeout(() => {
         console.log('這是箭頭函數',this)
    })
}

function Test2() {
    console.log(this);
    setTimeout(function () {
          console.log('這是普通函數',this)
    })
}    
let t1 = new Test1()
let t2 = new Test2()

輸出結果如下

VM90:2 Test1 {}
VM90:9 Test2 {}

VM90:4 這是箭頭函數 Test1 {}
VM90:11 這是普通函數 Window {window: Window, self: Window, document: document, name: "", location: Location, …}

原因是箭頭函數捕獲的是其所在上下文中的this值,而由於setTimeout()調用的代碼運行在所在函數完全分離的執行環境上,this指向的是window(其實我也沒咋明)

到這基本原因就明確了。

 

 

后面在我查找知識的時候,發現了let和var聲明的不同,貼下人家的代碼,這是在知乎找的(https://zhuanlan.zhihu.com/p/149239478)

 

var bar = {
    myName:"bar",
    printName: function () {
        console.log(myName)
    }    
}
let myName = "global"
let _printName = bar.printName
_printName() // global
bar.printName() // global

對於這個代碼都比較好理解,前面全局變量bar,myName,_printName的聲明,然后_printName聲明這行,bar.printName是一函數,讓變量_printName執行了這一函數

然后在全局作用域下直接調用了函數,則輸出的myName將在全局域中查找為global;最后一行相同原理

 

然后對代碼稍加更改

var bar = {
    myName:"bar",
    printName: function () {
        console.log(this.myName)
    }    
}
let myName = "global"
let _printName = bar.printName
_printName() // undefined
bar.printName() // bar

仍然是_printName變量執行函數bar.printName,這次執行時因為是全局作用域下,輸出的應該是window.myName。這下問題出來了,全局作用域下不是有myName嗎

非也,起初我也迷惑,但后來代碼放在控制台跑一下,發現其實let聲明變量的作用域並非全域,而是在script域中,也就是說全域並沒有myName這一變量,故輸出undefined

bar調用函數printName執行,則執行環境在bar塊作用域中,故輸出bar

 

 

萌新小白,請教

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM