js函数作用域预编译和作用域链闭包立即执行函数

Posted 石舟丿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js函数作用域预编译和作用域链闭包立即执行函数相关的知识,希望对你有一定的参考价值。


//函数声明
//函数创建的几种方式
//这是最基本的创建方式a是函数名

function a(){};

//命名函数创建方式
//该创建方法会忽略函数名只能使用a来调用该函数mun无法调用该函数

var a = function mun(){};

//匿名函数创建方式
//
//匿名函数不能直接使用。
//匿名函数可以依附于一个变量,并且这个变量名就是这个匿名函数的名字。

var b = function(){};

//当匿名函数用在绑定事件中的时候,当这个事件执行的时候这个匿名函数也会被执行

window.onload=function(){
console.log("我是匿名函数");
}

//立刻执行函数
//函数声明前加"+","-","!","||",等运算符会和立即执行函数一样
//如果将匿名函数放入到表达式中并且后面加上小括号会自动执行这个函数(立即执行函数)
//函数定义完,立刻被调用,这种函数叫做立即执行函数
//立即执行函数只会执行一次执行完成后会被垃圾回收机制回收
(function(a,b){
console.log(a);
console.log(b);
}(10,20));//立刻执行函数也是可以传递参数的

//函数中还有一个return属性返回值
//如果函数没有显示的使用 return语句 ,那么函数有默认的返回值:undefined

function show(a,b){
var c=a+b;
}
var a=show(3,6);
console.log(a);

//如果函数使用 return语句,那么跟再return后面的值,就成了函数的返回值

function show1(a,b){
var c=a+b;
return c;
}
var a = show1(3,6);
console.log(a);

//如果函数使用了return语句,但是return后面没有任何值,那么函数的返回值也是:undefined

function show2(a,b){
var c=a+b;
return ;
}
var a = show2(3,6);
console.log(a);

//函数作为返回值使用值
function fun(){
console.log("fun被调用");
return function(){
console.log("这是一个函数");
}
}
var y = fun()
y();


// JS是解释执行(解释一行执行一行)
// 全局变量如果页面不关闭,那么就不会释放,会占内存,消耗内存;
// 隐式全局变量:声明变量没用var;
// 全局作用域:全局变量的使用范围;
// 局部作用域:局部变量使用的范围;

//预编译分为局部预编译和全局预编译
//局部预编译
//预编译分四步
//1.在程序执行前创建AO对象(局部作用域),函数执行前产生的空间
//2.找到形参和变量声明,将变量和形参名作为AO的属性名,但是值为undefined
//3.将实参合形参统一;
//4.在函数体里找到函数声明,将值赋予函数体。
//列子
function fn(a){
console.log(a);//function
var a = 123;
console.log(a);//123
function a(){}
console.log(a);//123
var b = function (){}
console.log(b);//function
function d(){}
}
fn(1);
//第一步在程序执行前创建AO对象(局部作用域),函数执行前产生的空间
//AO{
//}
//第二步找到形参和变量声明,将变量和形参名作为AO的属性名,但是值为undefined
//AO{
// a:undefined
// b:undefined
//}
//第三步将实参合形参统一;
//AO{
// a:1
// b:undefined
//}
//第四步4.在函数体里找到函数声明,将值赋予函数体。
//AO{
// a:function
// b:function
// d:function
//}

//为了更加熟练在来一个列子
function test(a,b){
console.log(a);//function
console.log(b)//function
c = 0;
var c;
a = 3;
b = 2;
console.log(b);//2
function b(){}
function a(){}
console.log(a)//3
function b(){}
console.log(b);//2
}
test(6,5);
//第一步在程序执行前创建AO对象(局部作用域),函数执行前产生的空间
//AO{
//}
//第二步找到形参和变量声明,将变量和形参名作为AO的属性名,但是值为undefined
//AO{
// a:undefined
// b:undefined
// c:undefined
//}
//第三步将实参合形参统一;
//AO{
// a:6
// b:5
//}
//第四步在函数体里找到函数声明,将值赋予函数体。
//AO{
// a:function
// b:function
//}

//全局预编译
//有三步
//第一步生成一个GO对象
//第二步查找全局变量声明,变量名作为全局对象属性,值为undefined;
//第三步 查找函数声明,值为全局函数引用
//例子:
var l=10;
console.log(test);
function test(test){
console.log(test);//function
var test = 234;
console.log(test);
function test(){}//234
}
test(1);
var test = 123;

//第一步生成一个GO对象
//GO{
//}
//第二步查找全局变量声明,变量名作为全局对象属性,值为undefined;
//GO{
// test:undefined
// l:undefined
//
//}
//第三步 查找函数声明,值为全局函数引用
//GO{
// test:function
//}


//作用域
//1.[[score]]域:每个javascript都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供JavaScript引擎存取,[[score]]就是其中一个。
//[[score]]指的就是我们所说的作用域,其中存储了运行期上下下文的集合
//2.作用域链:[[score]]中所存储的执行期上下文对象的集合,这个集合呈链式连接;我们把这种链式连接叫做作用域链。(函数嵌套关系)
//3.运行期上下文:当函数执行时,会创建一个称为执行器上下文(AO GO)的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁。也可以理解为函数执行完后被释放

 

//闭包
//定义:当内部函数被保存到外部时会产生闭包,闭包会导致原有作用域链不释放,造成内存泄漏(内存被占用)。简单来说就是两个或多个函数嵌套把里面的函数保存到外部。
//来写个闭包的列子
function fun1(){
var a = 10;
function fun2(){
a++
console.log(a);
}
return fun2
}
var mung = fun1();
mung();
//闭包就是把函数往外抛出 只要是内部函数被保存到外部就会产生闭包
//让函数里的变量没有被清除一直存在函数中
//因为fun1的AO对象被mung引用了所以无法被垃圾回收器回收;
//闭包的作用有四种
//1.实现公有变量
//2.可以做缓存(存储结构)
//3.可以实现封装,属性私有化
//4.模块化开发防止污染全局变量

以上是关于js函数作用域预编译和作用域链闭包立即执行函数的主要内容,如果未能解决你的问题,请参考以下文章

预编译作用域链和闭包理解

JS 闭包

JS你不知道的JavaScript 笔记—— 作用域与闭包 - 编译原理 - LHS - RHS - 循环与闭包 - 模块 - 词法作用域 - 动态作用域

js_闭包

作用域链闭包和原型链

原型模式故事链--JS变量作用域作用域链闭包