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