js作用域详解

js对象

众所周知,js的所有数据类型都是一个对象,例如:

var a = 1;
console.log

声明a=1;a属于number类型,但是number类型又是number对象,有着以下方法:

interface Number {
    /**
      * Returns a string representation of an object.
      * @param radix Specifies a radix for converting numeric values to strings. This value is only used for numbers.
      */
    toString(radix?: number): string;

    /**
      * Returns a string representing a number in fixed-point notation.
      * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.
      */
    toFixed(fractionDigits?: number): string;

    /**
      * Returns a string containing a number represented in exponential notation.
      * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.
      */
    toExponential(fractionDigits?: number): string;

    /**
      * Returns a string containing a number represented either in exponential or fixed-point notation with a specified number of digits.
      * @param precision Number of significant digits. Must be in the range 1 - 21, inclusive.
      */
    toPrecision(precision?: number): string;

    /** Returns the primitive value of the specified object. */
    valueOf(): number;
}

更多关于js对象,可查看:https://codeplayer.vip/p/j7sh5

同样,声明一个函数,其实该函数属于window对象的一个方法:

例如,声明一个atest方法:

function atest() {
    console.log(1);
}

通过console控制台,我们可以看到:

仙士可博客

atest其实是一个window对象下的方法对象


var 局部变量作用域

var 声明一个对象,只作用域当前作用域以下。例如:

var a = 'test';
function b() {
    console.log(a);
}
b();

b函数可以成功调用上层作用域变量:

仙士可博客

但是不能被上层作用域调用:

仙士可博客

在顶级作用域下,var 声明变量,等于全局变量,被window对象接管:

<script>
var aaaa='666';
</script>

仙士可博客


定义全局作用域变量

直接定义不借助var,将定义全局变量,成为window对象的属性:

<script>
    var  a1='666';
    a2='777';
    function test() {
        a3='888';
    }
    test();
    console.log(a1,a2,a3);
</script>

仙士可博客


window对象直接赋值

window对象直接赋值方法,等同于不使用var 关键字定义:

<script>
    window.a1='666';
    window.a2='777';
    function test() {
        a3='888';
    }
    test();
    console.log(a1,a2,a3);
</script>

仙士可博客


同理,可以使用window对象,直接赋值一个函数:

<script>
    window.test = function () {
        console.log(666);
    };
    test();
</script>

仙士可博客


变量作用域覆盖问题

通过var 关键字我们知道,当声明一个变量时,该变量可以被当前作用域,以及下层作用域访问
当下层作用域存在同名变量时,下层变量将覆盖上层变量:

<script>
    var a=1;
  function atest() {
      btest();
      function btest() {
          var a=2;
          console.log('btest:'+a);
      }
      console.log("atest:"+a);
  }
  atest();
</script>

仙士可博客

同时,在子作用域声明的方法,只能在当前作用域或者下层作用域调用


闭包函数,闭包作用域

闭包函数,又称匿名函数,例如:

<script>
    (function () {
        var a = 1;
        console.log(a);
    });
    console.log(a);
</script>

该段函数并没有运行,因为它没有被调用:

仙士可博客

在声明函数之后,在后面增加括号即可实现声明后直接运行:

<script>
    (function () {
        var a = 1;
        console.log(a);
    })();
    console.log(a);
</script>

仙士可博客

赋值闭包函数

可通过赋值一个闭包函数,使其可以二次调用:

<script>
    var atest = function () {
        console.log('hello')
    };
    atest();
    atest();
</script>

仙士可博客


闭包函数增加括号并且赋值,变量将等于闭包函数返回的内容:(他将不再是一个函数,成为了一个函数返回值的对象)

<script>
    var atest = function () {
        var a='666';
        console.log('hello');
        return a;
    }();
    console.log(atest);
</script>

仙士可博客


闭包返回对象

可return一个json型对象,用于调用:

<script>
    var atest = function () {
        var a=1;
        return{
            a:2,
            b:3,
            c:function () {
                //返回上层闭包声明的a变量
                return a;
            }
        };
    }();
    console.log(atest.c());
    console.log(atest.a);//输出闭包return的json对象属性
    console.log(atest.b);
</script>

仙士可博客


在闭包函数中声明的变量,只能在闭包函数内的作用域,以及下层作用域使用,可通过return 对象中,通过return对象中声明的方法进行返回,使得上级作用域能成功访问到闭包作用域的变量


return作用域变量访问情况


在return作用域中的变量,外部可使用        匿名函数赋值的变量.变量名  方式访问,并且改值是引用型的,内部可使用  this.变量名方式

<script>
    var atest = function () {
        return{
            a:2,
            b:1,
            getA:function () {
                //返回上层闭包声明的a变量
                return this.a;
            },
            getB:function () {
                //返回上层闭包声明的a变量
                return this.b;
            }
        };
    }();
    console.log(atest.getA());
    console.log(atest.getB());
    atest.a=7;
    atest.b=6;
    console.log(atest.getA());
    console.log(atest.getB());
</script>


仙士可博客




总结

1:js万物皆对象,所有变量都是对象类型。

2:js的作用域是往下通用的,下层作用域可访问上层作用域的变量,并可修改值

3:js下层作用域变量和上层同名冲突时,下层作用域将覆盖上层变量,但上层作用域的访问不受影响

4:不适用var方法定义的变量,都属于全局变量,也就是window对象的属性

5:可通过window.方法定义全局变量

6:在顶层作用域声明的函数,其实就是window对象的方法

7:闭包在首次声明时,需要加括号自动调用,否则不能调用

8:闭包函数可通过赋值方法调用

9:闭包函数加括号 赋值到变量中,该变量将等于闭包的返回值

10:闭包返回值可返回一个对象,后期可使用  闭包赋值变量名.对象属性方法进行访问

11:闭包函数类var 的变量,只能在闭包函数下层或当前层使用,外部无法访问,但可以通过return 对象中,声明一个方法进行访问

12:闭包函数return的对象,都可以被  外部通过闭包赋值变量名.对象属性 应用,而对象本身也可以通过this.变量名,方式应用








仙士可博客
请先登录后发表评论
  • 最新评论
  • 总共0条评论
  • 本站由白俊遥博客程序搭建
    © 2017-1-17 php20.cn 版权所有 ICP证:闽ICP备17001387号
  • 联系邮箱:1067197739@qq.com