您的位置:首页 > Web前端 > JavaScript

js预处理和闭包

2017-12-10 17:49 113 查看

1.全局变量和函数执行分为两个阶段

(1)预编译阶段

①全局词法环境(lexicalenvironme)也就是执行上下文环境。用于存储预处理数据。预处理数据包括:var方式定义的变量和声明方式定义的函数;var方式定义的变量直接赋值undefine,声明方式定义函数赋值整个函数体,this赋值。

②预处理覆盖问题(函数以声明方式进行定义)

如果后声明的函数名和之前声明的函数名冲突,冲突函数后面的会覆盖前面的;

如果后声明的函数名和定义的属性名冲突,冲突函数后面的会覆盖前面的;

如果后定义的属性名和之前声明的函数名冲突,则会忽略属性定义。

③过程:•先初始化函数的参数到词法环境中;

       •内部声明方式定义的函数初始化到词法环境中;

       •初始化arguments属性;

       •内部var方式定义的变量初始化到词法环境中,赋值为undefine;

•函数和变量定义冲突处理方式和全局是一致的。

(2)执行阶段

从js代码块的第一行开始执行,并给词法环境中的变量赋值,如果变量在词法环境中不存在,则往词法环境中加入变量并赋值。

覆盖问题:执行阶段不会再处理声明方式定义的函数,声明方式定义函数不会覆盖任何定义的函数和属性,后赋值的属性会覆盖先赋值属性内容。

2.执行上下文栈

(1)定义:执行上下文的压栈和出栈过程



(2)原理:当执行全局函数时候,会产生一个执行上下文;

         每调用一次函数,同样会产生一个上下文;

         当函数调用完毕后,执行上下文会销毁。

如:

var a = 10,         //全局上下文环境

fn,

 bar = function(x){

  var b = 5;

  fn(x+b);          //fn上下文环境

 };

 fn = function(y){

  var c = 5;

  console.log(y+c);

 }

 bar(10);            //bar上下文环境

3.作用域

在JavaScript里,域指的是代码当前的上下文语境;js中作用域分为:全局作用域和本地作用域。JS中不存在块级作用域,即{}里的一个块。

(1)全局作用域:整个页面,全局域只能有一个,全局域有一个内置对象window

所有全局域的变量和方法都绑定到window对象上。

(2)本地作用域(函数作用域):在全局域中定义的域,通常指的是函数作用域,在函数内部定义的变量和函数。如果在一个新的域中定义了一些函数和变量,它们是无法从当前那个域的外部被访问的。

var a = 10,         //全局作用域

fn,

 bar = function(x){     //bar作用域

  var b = 5;

  fn(x+b);         

 };

 fn = function(y){        //fn作用域

  var c = 5;

  console.log(y+c);

 }
 bar(10);    

作用域只是一个“地盘”,一个抽象的概念,其中没有变量。要通过作用域对应的执行上下文环境来获取变量的值。同一个作用域下,不同的调用会产生不同的执行上下文环境,继而产生不同的变量的值。所以,作用域中变量的值是在执行过程中产生的确定的,而作用域却是在函数创建时就确定了。

所以,如果要查找一个作用域下某个变量的值,就需要找到这个作用域对应的执行上下文环境,再在其中寻找变量的值。     

4.作用域链

js中所有元素都是对象,包括function函数也是一个对象。任何一个函数对象都有一个内部属性。该内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问

取自由变量时的这个“作用域链”过程:(假设a是自由量)

(1)现在当前作用域查找a,如果有则获取并结束。如果没有则继续;

(2)如果当前作用域是全局作用域,则证明a未定义,结束;否则继续;

(3)(不是全局作用域,那就是函数作用域)将创建该函数的作用域作为当前作用域;

(4)跳转到(1)。

5.作用域和上下文环境的区别

(1)作用域在函数定义时就已经确定了,上下文环境在执行过程中产生;

(2)作用域是用于定义范围的,作用域内部的属性必须要通过上下文获取;

(3)作用域中变量的值是在执行过程中产生的确定的,而作用域却是在函数创建时就确定了;

(4)如果要查找一个作用域下某个变量的值,就需要找到这个作用域对应的执行上下文环境,再在其中寻找变量的值。

6.闭包(Closure)

(1)定义:闭包就是指外部能够随意读取其他函数内部变量的函数,也可以理解成“定义在一个函数内部的函数”,闭包是将函数内部和函数外部连接起来的桥梁。

(2)作用:可以读取函数内部的变量,减少全局变量定义;减少函数传递参数的数量;让函数内部变量的值始终保持在内存中,不会在函数调用完毕后被自动清除。

(3)全局作用域变量问题: 一个html文件中会包含大量的js外部文件引用;如果所有js文件全部使用全局作用域变量定义,则容易引起冲突。全局作用域变量定义访问效率低下,因为每次访问全局变量需要从作用域链中顶层找到底层。

注意事项:闭包使用父函数变量时候,只是个引用,而不是复制

父函数每调用一次,会产生不同的闭包。

函数声明和表达式的区别

表达式是由运算元和运算符(可选)构成,并产生运算结果的语法结构。

(function {})是表达式

function {}是函数声明.

闭包的两个条件:函数作为返回值;函数作为参数传递

(1)函数作为返回值

function f(){

var a  = 10;

return function f1(x){

if(x==a){

console.log(x);

     }

  };

}

var fn = f();

fn(12);

f1函数作为返回值,赋值给fn变量。执行fn(12)时,用到了f1作用域下的a变量的值

(2)函数作为参数传递

var a = 10;

fn = function(x){

if(x==a){

 console.log(x);

}

};

(function(f){

var a = 100;

f(15);

})(fn);

fn函数作为一个参数被传递进入另一个函数,赋值给f参数。执行f(15)时,max变量的取值是10,而不是100。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: