Javascript - 揭示对象和变量范围

时间:2012-08-14 12:59:23

标签: javascript variables inheritance scope

http://jsfiddle.net/ZLH7J/1/

下面显示的jsFiddle和代码是两个基本上做同样事情的例子。在任一示例中尝试调用first();this.first();时,都会引发未定义的错误。我可以稍后通过实例调用函数,但是在尝试使用init(){...}()像构造函数实例化对象时则不行。我把init()放在底层以为它是一个操作顺序,但事实并非如此。这不会像我认为的那样有效。

我很想知道应该怎么做,以及为什么不能这样做。

//create and return an obj
var fishSticks = function(){
    return {
        first: function(){
            document.getElementById('output').innerHTML="Success";
        },
        init: function(){
            try{
                first(); //err
                this.first(); // also err
             }catch(e){
                document.getElementById('output').innerHTML=e.toString();
            }
        }()
    }
}   

//do function stuff and then return 'this'
var fishFillet = function(){
    var first = function(){
            document.getElementById('output2').innerHTML="Success";
    }
    var init = function(){
            try{
                first(); //err
                this.first(); // also err
             }catch(e){
                 document.getElementById('output2').innerHTML=e.toString();
            }
    }()
return this;
}

 var test = new fishSticks();    
 var test2 = new fishFillet();

4 个答案:

答案 0 :(得分:1)

在您的第二个示例中,如果您将“init”中的呼叫注释到this.first(),则会收到“成功”消息。

第一个版本不起作用,因为JavaScript根本不允许在构造对象内对对象本身进行引用。没有办法做到这一点。

第二个工作(以及“第一个”工作的简单引用),因为“first”被声明为局部变量。局部变量是任何对象的属性,特别是它们不是在使用new调用函数时分配的对象的属性。这就是this.first()不起作用的原因。

在第二个问题中,您可以通过不同的方式宣传this.first()

var fishFillet = function(){
    this.first = function(){
            document.getElementById('output2').innerHTML="Success";
    }
    var init = function(){
            try{
                this.first(); //will work
             }catch(e){
                 document.getElementById('output2').innerHTML=e.toString();
            }
    }()
    return this;
}

此外,对于它的价值,还有奇怪的反模式

var something = function() { ... }

没有

那么有用
function something() { ... }

没有理由使用var声明而不是function声明。

答案 1 :(得分:1)

你需要了解两件事:

1)JavaScript不会像Java那样自动插入this,因此first()调用只会通过词法范围查看first的定义,它将会查看this对象。因此,对first()的调用应该有效,但this将绑定到除first内的预期之外的其他内容。

2)构造函数中的局部变量不会成为构造对象的成员。

答案 2 :(得分:1)

怎么样......

var fishFillet = function () {
    var first = function () {
        document.write( 'Success' );
    };

    var init = function () {
        first();
    };

    init();

    return {
        first: first
    };
};

然后:

var ff = fishFillet(); // calls init() which calls first()
ff.first(); // call first() manually

现场演示: http://jsfiddle.net/uaCnv/

因此,首先定义所有函数,然后手动调用init,最后返回一个包含那些应该通过结果对象可用的函数的对象(作为方法)。

答案 3 :(得分:1)

由于您将两者都用作构造函数,因此将它们格式化为:

function fishFillet(){
    this.first = function(){
        document.getElementById('output2').innerHTML="Success";
    }
    this.init = function(){
        try{
            this.first();
        }catch(e){
            document.getElementById('output2').innerHTML=e.toString();
        }
    }
}
var food = new fishFillet();
food.init();

它不适合你的原因是b / c“first”被创建为本地变量,并在execultion后被删除。在构造函数执行完成之后才会调用Init