函数作用域和块作用域

函数中的作用域:

属于这个函数的全部变量可以在整个函数的范围内使用以及复用(函数嵌套的作用域中也可以使用)

隐藏内部实现

代码片段+变量使用一个函数包装起来。实际上就是把这些函数里边的代码和变量隐藏起来了。
使用隐藏实现的原则
谁要使用这些函数或者变量,就把这些变量和函数放在谁的里边。

  function doSomething(a) {
      b=a+dosomethingElse(a*2);
      console.log(b*3);
  }
  function dosomethingElse(a) {
        return a-1;
  }
    var b=1;
    doSomething(2);  //15

上面的这个在功能上实现了,但是因为只有doSomething()这个函数用到了dosomethingElse()和b 其他函数都不会用到了这个两个变量,更合利的方式应该是将b和dosomethingElse()放在doSomething()内部,这样的做法更合理。

  function doSomething(a) {
      var b=1;
      b=a+dosomethingElse(a*2);
      console.log(b*3);
      function dosomethingElse(a) {
          return a-1;
      }
  }
    doSomething(2);  //15

这样b和dosomethingElse()就不会再被外部访问。体现的就是隐藏内部实现的原则。
设计API时使用隐藏内部实现的两个好处:
1、函数内部的这些被包装起来的bain两和函数不会被有意或者无意以非预期的方式使用
2、可以避免同名标识符之间的冲突。
设计API的时候使用隐藏内部实现的方法:
1、在全局作用域中申明一个名字足够独特的变量,然后第三方的所有的方法都会称为这个变量的属性
2、模块管理 所有的标识符都不能注入到共享域中,在保持私有、无冲突的作用域中,实现功能

函数作用域

任意代码片片段外部添加包装函数,可以将内部的变量和函数定义“隐藏”起来,外部作用域无法访问包装函数内部的任何内容。

  var a=2;
    function cc() {
        var a=3;
        console.log(a);   //3
    }
  cc();
    console.log(a);   //2

匿名和具名
一个典型的匿名函数的应用

  setTimeout(function () {
         console.log(1);
     },1000);

但是使用匿名函数有以下几个缺点:
1、匿名函数在追踪栈中不会显示有意义的函数名,使得调试很困难
2、如果没有函数名,当函数需要引用自身时只能使用已经过时的arguments.callee引用

 setTimeout(function () {
         console.log(1);
         arguments.callee();
     },1000);

上边这个程序是一个死循环,不可以随便运行。
3、函数省略了对于代码的可读性/可理解性很重要的函数名。函数名可以说明代码的功能。

 setTimeout(function timeoutHander() {
         console.log(1);
     },1000);

这样写更方便阅读。
立即执行的函数表达式IIFE

 var a=2;
    (function IIFE(global) {
        var a=3;
        console.log(a);//3
        console.log(global.a);  //2
    })(window);

使用立即执行函数表达式改变函数的执行顺序

 var a=2;
    (function IIFE(def) {
        def(window);
        console.log(1);   //最后输出的1 
    })(function def(global) {
        var a=3;
        console.log(a);   //3
        console.log(global.a);//2
    });

本来先写的console.log(1); 这句话,应该是先输出这句话,但是因为使用了立即执行的表达式所以将函数的执行的顺序弄反了,所以会先输出 2,3 再输出1

块作用域

js本身自己没有块级作用域
但是js中的for和if和with中的变量都会绑定到外部的作用域中。
if中的bar被绑定到了全局作用域中(if语句的当一层作用域中)

 var foo=true;
    if(foo){
        var bar=3;
        console.log(bar);
    }
    console.log(bar);

for中的ss被绑定到了全局作用域中(for的上一级作用域)

    for(var i=0;i<5;i++){
        var ss=i;
          console.log(ss);
    }
    console.log(ss);   //4

with中的a变量被绑定到了foo的上一级(全局)

  function foo(obj) {
       with (obj){
           a=4;
       }
   }
    var ob1={a:1};
    var ob2={b:2};
   foo(ob1);
   foo(ob2);
    console.log(ob1.a);    //4
    console.log(ob2.a);    //undefined
    console.log(a);      //4

let关键字:将变量绑定到任意的作用域中 ES6

    var foo=true;
    if(foo){
        let bar=2;
        console.log(bar); // 2
    }
  console.log(bar);   //Uncaught ReferenceError: bar is not defined

let和var的功能相同但是let可以将变量绑定到任意的作用域中。这时ES6提供一种除了var以为外的另一种定义变量的方式

const关键字 ES6

同样可以创建块级作用域变量,但是这个值是固定的以后任何程序的修改都会发生错误。

 var foo=true;
    if(foo){
        var a=2;
        const b=3;
        a=3;
        b=4;    //错误,因为不允许任何的程序对它进行修改
    }
    console.log(a);   //2
    console.log(b);   //Uncaught ReferenceError: b is not defined

ES6中的关键字const可以创建块级作用域。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值