JavaScript必备基础-预编译与立即执行函数

418 阅读3分钟

这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战

预编译

简单理解记忆

  1. 函数声明整体提升 系统会把函数提升到逻辑的最前面
  2. 变量 声明提升
    这两句话不能解决的问题
console.log(a);
function a(a) {
var a = 234;
var a = function () {
}
a();
}
var a = 123;


未经声明的变量归window所有

  1. imply global暗示全局变量:即任何变量,如果
    变量未经声明就赋值,此变量就为全局对象所有。
    eg:a= 123;eg: var a=b= 123;
  2. 一切声明的全局变量,全是window的属性。window就是全局的域
    eg:var a = 123; ===> window.a = 123;

预编译过程 发生在函数执行的前一刻

  1. 创建AO对象:执行期上下文
  2. 找形参和变量声明,将变量和形参名作为AO 属性名,值为undefined
  3. 将实参值和形参统一
  4. 在函数体里面找函数声明,值赋予函数体
    例子1:
function fn(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() {}
Fn(1);

预编译过程:AO{
a:function a () {}
b:undefined,
d:function d() {}
}


例子2

function test(a, b) {
console.log(a) ;//1
C=0;
var C;
a=3;
b=2;
console.log(b) ;//2
function b () {}
I
function d ( )
{}
console.log(b) ;//2
test(1);


例子3

function test(a, b) {
console.log(a) ;//function a () {}
console.log(b);//undefined
var b = 234;
console.log(b);//234
a = 123;
console.log(a);//123
function a () {}
var a;
b = 234;
var b = function ( ){}
console.log(a);//123
console.log(b) ;|//function () {}
}
test(1);


AO {
a:function
b:1
}
有全局的执行期上下文的时候

console.log(test);//function  text () { }
function test(test) {
console.log(test) ;//function text () { }
var test = 234;
console.log(test);//234
function test( ){
}
}
test(1) ;
var test = 123;


过程 :
在全局的执行期上下文:
GO {
text :function text () { }
}
函数执行的执行上下文
AO {
}

复杂的面试题例子:

 function test() {
      console.log(b);//undefined
      if (a) {
        var b = 100;
      }
        console.log(b)//undefined
        c = 234;
        console.log(c);//234
      }
      var a;
      test();
      // AO{
      //    b: undefined
      // }
      a = 10;
      console.log (b);//Uncaught ReferenceError: b is not defined
      console.log(c);//234

立即执行函数

上面的普通函数会产生变量提升,如果要顶一个一个函数定义的变量不会污染全局变量该怎么做呢,这个时候我们就可以用理解狮执行函数了

定义:此类函数没有声明,在一次执行过后即释放。适合做初始化工作。
作用:造出一个函数作用域,防止污染全局变量,它既不会提升,也不会污染全局对象,尽量的把功能封装在函数中
首先得知道,

  • 只有表达式才能被执行符号执行
  • 被执行符号执行的表达式他的名字会被自动忽略

当函数成为一个表达式时,它既不会提升,也不会污染全局对象。将函数变为一个函数表达式的方式之一,将函数用小括号括起来。
然而,这样一来,函数无法通过名称调用。如果书写一个函数表达式,然后将立即调用,该函数称之为立即执行函数 IIFE(Imdiately Invoked Function Expression)。
由于大部分情况下,函数表达式的函数名没有实际意义,因此,可以省略函数名。没有名字的函数,称之为匿名函数

//w3c建议写法:
    (function () {
            var a = 1,
                b = 2,
                c = 3;
            console.log(a, b, c);
        }());
//2.
 (function (){
            var a = 1,
                b = 2,
                c = 3;
            console.log(a, b, c);
        })(); 

上面说到了只有表达式才能被执行符号执行负责就会报错,但是有这个特殊情况

 function test(a, b, c,d) {
            console.log(a + b + C + d) ;
            }(1,2,3,4);

这里他不会报错,但也不会执行…他会分开执行

function test(a, b, c,d) {
            console.log(a + b + C + d) ;
            }




(1,2,3,4);