Javascript - 揭示对象和变量范围

Javascript - revealing object and variable scope

本文关键字:变量 范围 对象 Javascript      更新时间:2023-09-26

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();

你需要了解两件事:

1)JavaScript不会像Java那样自动插入this,所以first()调用只会在词法范围内查找first的定义,它会nok查看this对象。因此,对first()的调用应该有效,但this将绑定到与您在first中可能期望的其他内容不同的内容。

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

在第二个示例中,如果您注释掉"init"中的调用以this.first()则会收到"成功"消息。

第一个版本不起作用,因为 JavaScript 根本不允许在构造不足的对象中引用对象本身。 只是没有办法。

第二个有效(对"first"的简单引用有效),因为"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 声明。

怎么样...

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,最后返回一个对象,其中包含那些应该通过结果对象可用的函数(作为方法)。

由于您将两者用作构造函数,因此请按以下格式设置它们:

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"被创建为本地变量,并在执行后被删除。在构造函数的执行完成之前不会调用 Init