关于全局对象和变量声明
今天复习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.num
和 var 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