深挖Javascript全局对象属性和变量声明的关系

关于全局对象和变量声明

今天复习js的学习视频,讲构造函数的时候补充了下构造函数和普通函数的this指向问题,其中谈到了window对象。

都知道构造函数的this指向的是实例化的那个对象,而普通函数的this指向的其实就是window对象。所以会出现这种情况:

function f1(){
    
    
    console.log(this);   
}
f1();     //这里调用后打印出来的会是window对象

而alert等函数,其实都是window全局对象下的成员,window可以省略:

alert('123');
window.alert('123');   //这两个是等同的

而我们声明的变量,其实也会成为window对象的属性:

let num = 100;
console.log(window);   
//-> 会发现window对象里会多出一个属性num,值为100

想起这样一句话:“JS里万物皆对象”。我突然想到,这种变量声明,其实是不是就是给window对象添加属性?这两者是不是等同的?换言之:

全局作用域中**window.numvar num 是不是一样的?**

抱着这种想法,我做了下测试:

//测试直接给window添加属性,能不能向变量一样仅凭属性名就打印?
window.num = 10;
alert(num);    //-> 10
//果然,测试的结果是,num可以正常打印

//那再使用变量重新声明呢?
window.age = 18;
var age = 20;    
alert(age);   //-> 20
//果然,打印出来的是重新声明的值,这是不是意味着window.age这个属性被变量声明给“覆盖”了呢?
alert(window.age);  //-> 20
//说明确实被覆盖了

//反过来也一样
var name = 'Jack';
window.name = 'Nick';
alert(window.name);   //-> Nick
//一次性打印两个时
console.log(window.name,name);  //-> Jack Jack

//看看两者是否相等:
console.log(window.name===name);   //-> true

然后我翻了下《JavaScript高级程序设计》这本书,window对象中有这样一段话:

因为window对象被复用为ECMAScript的Global对象,所以通过var声明的所有全局变量和函数都会变成window对象的属性和方法。比如:

var age = 29;
var sayAge = () => alert(this.age);

alert(window.age);  // 29
sayAge();   // 29
window.sayAge();  //29

还有这样一段话:

但是使用let或const替代var,则不会把变量添加给全局对象。

也就是说会出现这种情况:

window.age = 18;
let age = 20;    
console.log(age , window.age);   //-> 20 18   
//两个都可以正常打印,值互不干扰

const num = 10;
console.log(window.num);   //-> undefined

另外,访问为未声明的变量会抛出错误,但是可以在window对象上查询是否存在可能未声明的变量:

var newVal = oldval;  //会抛出错误,因为oldVal没有声明

var newValue = window.oldvalue;
//这里不会抛出错误,因为这里是属性查询
//newValue会被设置成undefined

猜你喜欢

转载自blog.csdn.net/Lu_xiuyuan/article/details/112987642