js预编译

将代码封装成函数的形式,可以减少代码的耦合(编程追求的是高内聚,弱耦合)

函数声明:

  function sayhello(){

    console.log('hello world')

  }

函数表达式:(一般指的匿名函数表达式)

  命名函数表达式:

  var say = function sayhello(){

    console.log("hello world")

  }

  匿名函数表达式:

  var say1 = function(){

    console.log("hello world")

  }

命名函数表达式与匿名函数表达式唯一的区别:

  console.log(say.name)   ==>   sayhello 

  console.log(say1.name)    ==>   say1

在ES5以前,作用域分为两种:全局作用域,局部作用域(也称函数作用域)

1.任何变量,如果变量未经过声明就赋值,此变量就归全局所有
2.arguments  类数组对象,记录的是所有的实参集合

每个function都会生成一个自己作用域

var a = 123;

function fun(){

  var c = 234;

  console.log(a,c) ==>都有返回值(在局部作用域中可以访问全局作用域的变量)

}

fun(); 

console.log(a)  ==>a为全局变量,有返回值

console.log(c)  ==>c为局部变量,全局作用域中没有,会报错(全局作用域中不能访问局部作用域的变量)

  注意console.log(name)  不会报错,name是window的自带属性

函数执行前的流程,在执行函数fun()前,浏览器会做3件事:

  1.语法分析  检测代码有没有低级错误(有会报错)

  2.预编译      

  3.根据编译好的来逐行执行

预编译:

  1.函数运行前的一瞬间,会生成一个AO对象(Active Object),简称AO,执行期上下文

  2.分析参数,形参作为AO对象的属性名,实参作为AO对象的属性值

  3.分析变量声明,变量名为属性名,值为undefined,如果遇到同名的不做任何改变

  4.分析函数声明,函数名为属性名,函数值为函数体,如果遇到同名的直接覆盖

函数执行一次,就会产生一次预编译的过程,预编译是执行前的过程

实例: 

function fun(a){

  var b = 123;

  function c(){

    var d = 234;

  }

}

fun(6);

预编译:

1.在函数fun运行前的一瞬间,生成一个AO对象(为函数c的GO)

  fun.AO = {};

2.分析参数(假如没有,略过)

  fun.AO ={

    a : 6

  }

3.分析变量(假如没有,略过)

  fun.AO ={

    a : 6,

    b : undefined

  }

4.分析函数声明(假如没有,略过),最终:

  fun.AO ={

    a : 6,

    b : undefined,

    c : function(){

      var d = 234;

    }

  }

然后根据AO对象执行函数,当函数执行完成后,AO对象会自动销毁

作用域:

全局作用域 --相对的
函数作用域 --只要出现function就会产生自己的作用域

函数本身也是一个对象
fn.name
fn.length
fn.prototype
fn.[[scope]] 看不到的属性,给系统内部去读 简单一点理解:放的就是GO和AO
把[[scope]]的集合构成链状的形式,就形成作用域链,本质就是一个JavaScript对象

执行期上下文:当函数执行的时候,会创建一个执行期上下文的内部对象,存储了定义好的变量,函数...
执行期上下文属于独一无二的,每当你函数调用一次,就会产生新的执行期上下文,当你的函数运行完成,执行期上下文就会被销毁

闭包:

function a(){
  var num = 100;
  function b(){
    num ++;
    console.log(num);
  }
  return b;
}
var demo = a();
demo() 》 101
demo() 》 102

b 执行 --> demo() b.[[scope]] 0 : b.AO num++
1 : a.AO
2 : GO

坏处: 作用域链得不到释放,造成内存的泄露

好处: 累加器
做缓存
封装
模块化开发,避免全局污染

只能通过指定的接口去访问或者操作内部变量


 闭包做缓存

function test(){
  var num = 100;
  function a(){
    num ++;
    console.log(num)
  }
  function b(){
    num --;
    console.log(num)
  }
  return [a,b]
}
var arr = test();
arr[0]();
arr[1]();

猜你喜欢

转载自www.cnblogs.com/d-laowu/p/9224632.html
今日推荐