Javascript作用域的范围

时间:2014-03-10 20:46:53

标签: javascript

我知道Javascript中的所有内容都是一个对象,但是如何在一个范围内声明一个变量呢?我的意思是仅仅作为一个变量,并突然开始使用它作为一个对象分配一些属性“INSIDE”其他功能。该案例的范围界定如何运作?

https://github.com/ariya/esprima/blob/master/esprima.js

在此代码中,仅在没有给出任何属性的情况下声明额外变量:

var Token,
    extra;

突然它开始被对象使用如下:

function addComment(type, value, start, end, loc) {
    var comment, attacher;

    assert(typeof start === 'number', 'Comment must have valid position');

    // Because the way the actual token is scanned, often the comments
    // (if any) are skipped twice during the lexical analysis.
    // Thus, we need to skip adding a comment if the comment array already
    // handled it.
    if (state.lastCommentStart >= start) {
        return;
    }
    state.lastCommentStart = start;

    comment = {
        type: type,
        value: value
    };
    if (extra.range) {
        comment.range = [start, end];
    }
    if (extra.loc) {
        comment.loc = loc;
    }
    extra.comments.push(comment);

    if (extra.attachComment) {
        attacher = {
            comment: comment,
            leading: null,
            trailing: null,
            range: [start, end]
        };
        extra.pendingComments.push(attacher);
    }
}

我可以从这个额外作为对象启动的最接近的示例来自以下函数:

function tokenize(code, options) {
    var toString,
        token,
        tokens;

    toString = String;
    if (typeof code !== 'string' && !(code instanceof String)) {
        code = toString(code);
    }

    delegate = SyntaxTreeDelegate;
    source = code;
    index = 0;
    lineNumber = (source.length > 0) ? 1 : 0;
    lineStart = 0;
    length = source.length;
    lookahead = null;
    state = {
        allowIn: true,
        labelSet: {},
        inFunctionBody: false,
        inIteration: false,
        inSwitch: false,
        lastCommentStart: -1
    };

    extra = {};

    // Options matching.
    options = options || {};

    // Of course we collect tokens here.
    options.tokens = true;
    extra.tokens = [];
    extra.tokenize = true;
    // The following two fields are necessary to compute the Regex tokens.
    extra.openParenToken = -1;
    extra.openCurlyToken = -1;

    extra.range = (typeof options.range === 'boolean') && options.range;
    extra.loc = (typeof options.loc === 'boolean') && options.loc;

    if (typeof options.comment === 'boolean' && options.comment) {
        extra.comments = [];
    }
    if (typeof options.tolerant === 'boolean' && options.tolerant) {
        extra.errors = [];
    }

    if (length > 0) {
        if (typeof source[0] === 'undefined') {
            // Try first to convert to a string. This is good as fast path
            // for old IE which understands string indexing for string
            // literals only and not for string object.
            if (code instanceof String) {
                source = code.valueOf();
            }
        }
    }

    try {
        peek();
        if (lookahead.type === Token.EOF) {
            return extra.tokens;
        }

        token = lex();
        while (lookahead.type !== Token.EOF) {
            try {
                token = lex();
            } catch (lexError) {
                token = lookahead;
                if (extra.errors) {
                    extra.errors.push(lexError);
                    // We have to break on the first error
                    // to avoid infinite loops.
                    break;
                } else {
                    throw lexError;
                }
            }
        }

        filterTokenLocation();
        tokens = extra.tokens;
        if (typeof extra.comments !== 'undefined') {
            tokens.comments = extra.comments;
        }
        if (typeof extra.errors !== 'undefined') {
            tokens.errors = extra.errors;
        }
    } catch (e) {
        throw e;
    } finally {
        extra = {};
    }
    return tokens;
}

但它仍然只在这个函数内部,而不是与

相同的范围
var Token,
    extra;

如何声明变量并仅实例化函数内的属性?它是如何在不同的范围之间共享的?一旦在一个函数中给出属性,它是否与其他作用域中的另一个作用域共享?太混乱了。

2 个答案:

答案 0 :(得分:1)

Line #3658将其设置为空对象:

extra = {};

答案 1 :(得分:0)

范围界定与标识符(即名称)与它们所引用的内容的匹配有关。对于在一个作用域中创建的对象要从另一个作用域访问,您只需要在每个对象中都有一个名称引用相同的东西(例如,通过将函数中创建的对象返回给其调用者并让调用者将其分配给名称在其范围内的变量。)