js变量作用域
第一种:没有使用var修饰,定义的是全局变量,在严格模式下该方法不能使用
i = 0;
第二种:使用var修饰,没有定义在函数体内是被认为是window属性,是全局属性,定义在函数体内时是局部属性,仅在当前函数体有效,函数体外无法访问
var i = 0;
第三种:向指定路径添加属性
function fun(){
fun.i= 0;
};
我们知道,在js中所有对象都是window的属性,所以这种定义方法就相当于window.fun.i=0。通过这种方法定义的变量能够在函数体外被访问。
所以
1.
function fun(){
vari = 0;
}
alert(fun.i) //undefined
2.function(){
fun.i= 0;
}
alert(fun.i) //0
沿原型链查找变量
任意一个function都有8个内置属性
1. arguments:null
2. caller:null
3. length:0
4. name:"abc"
5. prototype:{constructor: ƒ}
6. __proto__:ƒ ()
7. [[FunctionLocation]]:question1.html?_ijt=…rgnjroisq25f076v:12
8. [[Scopes]]:Scopes[1]
其中prototype属性指向该函数的原型,__proto__指向该函数的构造函数
说明Object.prototype.__proto__为什么等于null:
f1.__proto__=Foo.prototype
f1.__proto__.__proto__=Object.prototype
f1. .__proto__.__proto__.__proto__=null
在原型链查找的过程中,查找f1. .__proto__.__proto__.__proto__就停止了,如果把Object.prototype.__proto__指向Object.prototype或者Function.prototype则会使程序陷入死循环。
我们知道js是通过原型链查找的,通过原型链查找是每次都给要查找的变量前面加__proto__,所以说它不是沿着prototype查找的,而是沿着__proto__查找的。
下面说明window是继承子object函数的。
执行console.log(window),在最后一行找到__proto__,可以看到,window的构造函数是f Window(){},window对象的原型是Window.prototype,打开window.__proto__.constructor(即函数f Window()),可以看到f Window(){}的构造函数是f WindowProperties(),可以看到window.__proto__.__proto__是WindowProperties.prototype,继续往下可以看到f WindowProperties()的构造函数是ƒ EventTarget(),ƒ EventTarget()__proto__是Object,即
console.log(window.__proto__.__proto__.__proto__.__proto__) //Object
由此可以得出,在js中window对象也是Object的子对象。
当你在使用一个没有指定使用者的变量i时,就会默认使用window.i,因此当你把一个变量声明在Object.prototype时,就会顺着原型链window.__proto__.__proto__.__proto__.__proto__.i找到这个变量。
所以对于以下情况
function fun(){
fun.i = 9;
alert(i);
}
输出为undefined。因为这个变量被定义在window.fun.i,在window的原型链中没有这个变量。
在js中所有对象都是window的对象,所以对于当你输入fun.i调用这个对象时默认是window.fun.i。
对于一个稍微复杂一点的情况:
var k = {u:3} var l = {o:2} l.__proto__ = k function abc() {} abc.prototype.__proto__ = l abc() alert(abc.u) //undefined
其中abc.u等同于window.abc.u,会在abc构造函数(f Function())这条原型链中查找,而这个变量被定义在了abc的原型这条原型链当中,所以输出undefined,把代码最后一句改成abc.prototype.u就可以输出3了。
也就是说通过abc.u可以访问定义在function原型中的属性,即
Function.u = 9;
function abc() {};
alert(abc.u) //9
需要注意并不是所有的对象都是继承Object,可以通过修改属性来使得它不继承任何对象。
K={
__proto__:null
}
但是所有对象都一定使window的属性或方法。 上面第一个图片来自不知道哪个网友的,很有用的个图片,既然不知道是谁的图,我们可以感谢祖国