zoukankan      html  css  js  c++  java
  • JavaScript——变量作用域

    在javascript中, var 定义变量实际是有作用域的。

    1、var变量作用域问题

    1.2、假设一个变量在函数体中声明,则该变量的作用域为整个函数体则在函数体外不可以使用。

    function qj() {
        var x = 1;
        x = x + 1;
    }
    
    x = x + 2; //Uncaught ReferenceError: x is not defined    无法在函数体外引用变量x
    

    1.2、如果两个函数使用了相同的变量名,只要在函数内部,就不冲突

    function qj() {
        var x = 1;
        x = x + 1;
    }
    
    function qj2() {
        var x = 'A';
        x = x + 1;
    }
    

    1.3、内部函数可以访问外部函数的成员,反之则不行

    function qj() {
        var x = 1;
    
        // 内部函数可以访问外部函数的成员,反之则不行
        function qj2() {
            var y = x + 1;  // 2
        }
    
        var z = y + 1; // Uncaught ReferenceError: y is not defined
    }
    

    1.4、假设,内部函数变量和外部函数的变量重名

    function qj() {
        var x = 1;
    
        function qj2() {
            var x = 'A';
            console.log(' x in qj2()='+x); // x in qj()=1
        }
        console.log('x in qj()='+x); //x in qj2()=A
        qj2()
    
    }
    
    qj()
    

    结论:假设在JavaScript 中 函数查找变量从自身函数开始,由 ‘’内‘’ 向 ‘’外‘’ 查找 . 假设外部存在这个同名的函数变量,则内部函数会屏蔽外部函数的变量。

    2、提升变量的作用域

    JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:

    'use strict';
    function qj() {
        var x = "x" + y;
        console.log(x);
        var y = 'y';
    }
    
    qj() //x undefined
    

    问题:为什么会出现 x undefined?

    说明:虽然是strict模式,但语句并不报错,var x = "x" + y;原因是变量y在稍后申明了。但是console.log显示x undefined,说明变量y的值为undefined。这正是因为JavaScript引擎自动提升了变量y的声明,但不会提升变量y的赋值。

    对于上述qj()函数,JavaScript引擎看到的代码相当于:

    function qj() {
        var y;
        var x = "x" + y;
        console.log(x);
        y = 'y';
    }
    

    这个是在JavaScript建立之初就存在的特性。养成规范: 所有的变量定义都放在函数的头部,不要乱放,便于代码维护;

    function qj2() {
        var x = 1,// x初始化为1
            y = x + 1,// y初始化为2
            z,i; //z和i为undefined
    
        //其他语句
    }
    

    3.全局函数

    不在任何函数内定义的变量就具有全局作用域。实际上,JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性:

    x = 1;
    
    function f() {
        console.log(x);
    }
    f();  //1
    console.log(x);  //1
    

    3.1、全局对象 window

    var x = 'xxx';
    alert(x);
    alert(window.x); // 默认所有的全局变量,都会自动绑定在 window对象下;
    

    3.2、alert() 这个函数本身也是一个 window 变量

    var x = 'xxx';
    
    window.alert(x);
    
    var old_alert = window.alert;
    
    old_alert(x);//xxx
    
    window.alert = function () {
    
    };
    window.alert(123);// 发现 alert() 失效了
    
    //恢复
    window.alert =  old_alert;
    window.alert(456);
    
    

    Javascript 实际上只有一个全局作用域, 任何变量(函数也可以视为变量),假设没有在函数作用范围内找到,就会向外查找,如果在全局作用域都没有找到,报错 RefrenceError

    4、规范

    由于我们所有的全局变量都会绑定到我们的 window 上。如果不同的js 文件,使用了相同的全局变量,就会造成命名冲突,并且很难被发现

    如何能够减少冲突?

    把自己的代码全部放入自己定义的唯一空间名字中, 降低全局命名冲突的问题~

    // 唯一全局变量
    var MYAPP = {};
    
    // 定义全局变量
    GodlesApp.name = 'myapp';
    //其他函数
    MYAPP.add = function (a,b) {
        return a + b;
    }
    

    5、局部作用域 let

    'use strict';
    function aaa() {
        for (var i = 0; i < 100; i++) {
            console.log(i)
        }
        console.log(i+1); //101  
    }
    

    问题: 为什么i出了这个作用域还可以使用?

    ES6 let 关键字,用let替代var可以申明一个块级作用域的变量

    'use strict';
    function aaa() {
        for (let i = 0; i < 100; i++) {
            console.log(i)
        }
        console.log(i+1); //Uncaught ReferenceError: i is not defined
    }
    

    建议大家都是用 let 去定义局部作用域的变量;

    6、常量 const

    在ES6 之前,怎么定义常量?只有用全部大写字母命名的变量就是常量;建议不要修改这样的值

    var PI = '3.14';
    console.log(PI); //3.14
    PI = '213'; 
    console.log(PI); //213 可以改变这个值
    

    在 ES6 引入了常量关键字 const

    const PI = '3.14'; // 只读变量
    console.log(PI);  //3.14
    PI = '123'; // TypeError: Assignment to constant variable.
    console.log(PI); //3.14
    

    7、解构赋值

    从ES6开始,JavaScript引入了解构赋值,可以同时对一组变量进行赋值。

    7.1、传统赋值

    //如何把一个数组的元素分别赋值给几个变量?
    var array = ['hello', 'JavaScript', 'ES6'];
    var x = array[0];
    var y = array[1];
    var z = array[2];
    

    7.2、ES6赋值

    'use strict';
    // 如果浏览器支持解构赋值就不会报错:
    var [x, y, z] = ['hello', 'JavaScript', 'ES6'];
    // x, y, z分别被赋值为数组对应元素:
    console.log('x = ' + x + ', y = ' + y + ', z = ' + z);
    //x = hello, y = JavaScript, z = ES6
    

    注意:对数组元素进行解构赋值时,多个变量要用[...]括起来。

    7.2.1、如果数组本身还有嵌套,也可以通过下面的形式进行解构赋值,注意嵌套层次和位置要保持一致:

    let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']];
    x; // 'hello'
    y; // 'JavaScript'
    z; // 'ES6'
    

    7.2.2、解构赋值还可以忽略某些元素:

    let [, , z] = ['hello', 'JavaScript', 'ES6']; // 忽略前两个元素,只对z赋值第三个元素
    z; // 'ES6'
    

    7.2.3、如果需要从一个对象中取出若干属性,也可以使用解构赋值,便于快速获取对象的指定属性:

    'use strict';
    
    var person = {
        name: '小明',
        age: 20,
        gender: 'male',
        password: '123456',
        school: 'No.1 middle school'
    };
    var {name, age, passport} = person// name, age, passport分别被赋值为对应属性
    console.log('name = ' + name + ', age = ' + age + ', password = ' + password);
    //name = 小明, age = 20, passport = 123456
    
  • 相关阅读:
    【技巧总结】公开漏洞学习
    【 Keepalived 】Nginx or Http 主-主模式
    【 Keepalived 】Nginx or Http 主-备模式
    【 转 】Keepalived工作原理
    【 总结 】crontab 使用脚本及直接获取HTTP状态码
    【 总结 】linux中test命令详解
    【 总结 】Tcp Keepalive 和 HTTP Keepalive 详解
    【 Linux 】I/O工作模型及Web服务器原理
    【 Ngnix 】配置路径转发至后端Apache多台虚拟主机
    【 Linux】脚本导入格式
  • 原文地址:https://www.cnblogs.com/godles/p/12196167.html
Copyright © 2011-2022 走看看