zoukankan      html  css  js  c++  java
  • Javascript中的作用域(scope)

    类 C 语言一般都用于块级作用域,但是Javascript中的 while, if-else, for, switch-case 等控制结构不具有自己的作用域,

    在Javascript中只有函数(function)具有自己的作用域,请比较如下的 C# 代码和 Javascript 代码:

    // C# 中 for 循环有自己的作用域
    for (int i = 0; i < 5; i++)
    {
        
    //
    }
    Console.WriteLine(i); 
    // 当前上下文中不存在名称“i”
    // Javascript中 for 循环没有自己的作用域
    for (var i = 0; i < 5; i++) {
        
    // do something
    }
    console.log(i);   
    // 5


    但是,Javascript中的函数有自己的作用域,如下示例:

    // function 拥有自己的作用域
    (function() {
        
    var j = 6;
    })();
    console.log(
    typeof (j)); // 'undefined'
    // function 中使用和全局变量相同名称的局部变量
    var i = 5;
    (
    function() {
        
    var i = 1;
    })();
    console.log(i);   
    // 5

    在函数中不使用 var 关键字声明的变量,就会在全局范围内查找,如下:

    var i = 5;
    (
    function() {
        i
    ++;    // 此时的i是全局变量
    })();
    console.log(i);   
    // 6

    这里就有一个可能让人迷惑的代码,如下:

    var i = 6;
    (
    function() {
        i
    ++;    // 此时的i是局部变量,但是未定义(undefined),undefined + 1 == NaN
        console.log(isNaN(i));    // true
        var i;
    })();
    console.log(i);   
    // 6


    或许你会觉得函数中 i++, 引用的岂不是全部变量?

    答案是否定的,只要在函数内拥有相同名称的局部变量定义,那这个变量就是局部的。

    那我们如何在函数内引用和局部变量相同名称的全局变量呢?

    答案是使用命名前缀。考虑如下代码:

    var i = 6;
    (
    function() {
        window.i
    ++;    // 此时的i是局部变量
        var i = 1;
    })();
    console.log(i);   
    // 7


    正因为自执行的匿名函数,可以用来向外部隐藏属性,我们可以用这个特性在Javascript中实现私有属性。

    考虑如下获取随机数([0,10])的对象:

    var random1 = {
        _num: 
    -1,
        _init: 
    function() {
            
    // 随机一个大于等于0,小于等于10的整数
            this._num = Math.round(Math.random() * 10);
        },
        getNum: 
    function() {
            
    if (this._num === -1) {
                
    this._init();
            }
            
    return this._num;
        }
    };
    console.log(
    'random1._num == ' + random1._num); // -1
    console.log('random1.getNum() == ' + random1.getNum()); // [0,10]


    虽然我们的意图是想向外界隐藏 _num 变量和 _init 属性,不过这个目的显然没有达到,用户仍然可以通过 random1._init(); 的方式调用。

    我们需要是用Javascript中函数特有的性质(拥有自己的作用域),使用自执行的匿名函数来达到隐藏属性的目的。

    考虑如下解决办法:

    var random2 = {};
    (
    function() {
        
    var _num = -1;

        
    function _init() {
            _num 
    = Math.round(Math.random() * 10);
        }

        random2.getNum 
    = function() {
            
    if (_num === -1) {
                _init();
            }
            
    return _num;
        };
    })();
    console.log(
    'random2._num == ' + random2._num); // 'undefined'
    console.log('random2.getNum() == ' + random2.getNum()); // [0,10]


    代码下载

  • 相关阅读:
    33.数组声明方式(var构造函数) 、检测数组类型、数组的属性(封装好的就一个length)、数组的方法
    31.this指向(写出调用链,找最近对象) this的默认绑定 隐式绑定 显示绑定(call(绑定对象) apply(绑定对象) 当括号内没放绑定对象的时候恢复默认绑定) bind
    31.
    30.函数作用域链 (GO AO 也叫词法作用域链)、 调用栈、调用栈涉及this绑定
    29.包装类(构造函数) 包装类作用及调用栈
    916. Word Subsets
    246. Strobogrammatic Number
    445. Add Two Numbers II
    2. Add Two Numbers
    341. Flatten Nested List Iterator
  • 原文地址:https://www.cnblogs.com/sanshi/p/javascript_scope.html
Copyright © 2011-2022 走看看