js中有暗示全局变量:任何变量如果未经声明就赋值,此变量就为全局对象所有(不管在哪里)。
a = 10;
console.log(window.a) //10
window
就是全局的域。一切声明的全局变量,全是window
的属性。
var a = 123;
console.log(window.a) //123
-
js函数预编译四部曲
预编译结束后执行函数:
function test(a){
console.log(a); //function a(){}
var a = 123
console.log(a); //123
function a(){}
console.log(a); //123
var b = function(){}
console.log(b);//function(){}
function d(){}
}
-
全局预编译三部曲:
1、生成一个GO
对象(Global Object)就是window
。
2、找变量声明,将变量名作为GO
属性名,值为undefined
。
3、找函数声明(注意不是函数表达式),值赋予函数体。
知识点: 1、
GO
发生在AO
前。 2、形参和实参有映射规定:形参变,实参也变。实参出生有几个就几个,不对应形参个数就不映射。3、typeof(NaN) // "Object"
作用域
运行期上下文:当函数执行前一刻,会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁。
[[scope]]:每个javascript函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供javascript引擎存取,[[scope]]就是其中一个。
[[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合。
作用域链:[[scope]]中存储着执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。(每个函数都有自己的作用域链)
查找变量:在哪个函数中查找就从这个函数作用域链的顶端依次向下查找。(在全局定义的函数,它的运行期上下文就是全局域)。
function a(){
function b(){
var b = 234;
}
var a = 123;
b();
}
var glob = 100;
a();
//a函数被定义时产生 a.[[scope]] --> 0:GO{}
//a函数被执行时 a.[[scope]] --> 0:AO{}
// 1:GO{}
//b函数被定义时 b.[[scope]] --> 0:AO{} a的AO
// 1:GO{}
//b函数被执行时 b.[[scope]] --> 0:AO{} b的AO
// 1:AO{} a的AO引用
// 1:GO{}
a函数被定义时.png
a函数执行.png
b函数被定义时.png
b函数被执行时.png
闭包
当内部的函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造成内存泄漏。
function a(){
function b(){
var bbb = 234;
consoloe.log(aaa);
}
var aaa = 123;
return b;
}
var glob = 100;
var demo = a();
demo();
闭包作用域链.png
-
闭包的作用:
- 1.实现公有变量
- eg:函数累加器
- 2.可以做缓存(存储结构)
- eg:eater
- 3.可实现封装,属性私有化。
- eg:Person();
- 4.模块化开发,防止污染全局变量
- 1.实现公有变量
1.就是闭包实现累加
function add(){
var count = 0;
function demo(){
count ++;
console.log(count);
}
return demo;
}
var counter = add();
counter(); //1
counter(); //2
2.可以做缓存(存储结构)
function test(){
var num = 100;
function a(){
num ++;
console.log(num);
}
function b(){
num --;
console.log(num);
}
return [a,b];
}
var myArr = test();
myArr[0](); //101
myArr[1](); //100
function fn(name){
var _age;
function setAge(n){
_age = n;
}
function getAge(){
return _age;
}
return{
name:name,
setAge:setAge,
getAge:getAge
}
}
var p1 = fn("张三");
p1.setAge(20);
console.log(p1.getAge());//20
console.log("姓名:"+p2.name+",年龄:"+p2.getAge()); //姓名:张三,年龄:20