2013-07-02 63 views
0

在以下示例中,为什么'z'声明会导致语法错误?在自执行函数中声明函数的正确方法是什么?

(function(){ 

    function x(){return 'this is x'}; 
    y = function(){return 'this is y'}; 

    //z : function(){return 'this is z'}; 

    alert(x()); 
    alert(y()); 
    //alert(z()); 

})(); 

http://jsfiddle.net/VXPsd/2/

+0

因为你不在对象范围内的语法明智... – CBroe

+0

你为什么会想到上班? – SLaks

+0

有道理,所以我想简短的答案是一个函数(匿名或命名)不支持属性声明?感谢您的出色答复。 – 4m1r

回答

3

...为什么 'Z' 的声明导致语法错误?

因为您在对象初始值设定项之外使用属性初始值设定项语法。

这是一个对象初始化(位开始{}结尾)包含属性初始化(中线):

var obj = { 
    propertyName: "property value" 
}; 

所以,如果你声明一个对象,你可以用你的z线(不;):

var obj = { 
    z: function() { return 'this is z'} 
}; 

但是,你必须在你的代码,你在一个对象初始化不是,你在一个函数体是。所以你不能使用这种语法。

值得注意的是,您的xy是完全不同的结构。

此:

function x(){return 'this is x'}; 

是一个功能声明。函数声明在包含函数中的任何逐步代码运行之前进行处理,并且函数名称位于包含函数顶部的范围内。 (有时人们称之为 “冲顶”。)

此:

y = function(){return 'this is y'}; 

是一个功能表达。它与所有表达式一样,在包含函数中逐步执行代码时遇到。

(代码所引用的瀑布猎物The Horror of Implicit Globals,顺便说一句:既然在上y没有var,既然你不使用严格模式,该行创建了一个全球变量称为y。)

在自执行函数中声明函数的正确方法是什么?

无论是书(xy形式)比其他的更正确的(撇开隐性的全球事情)。他们每个人都有使用,这取决于你在做什么。 y表单有一个问题,即函数y引用没有名称(这是一个匿名函数  —它分配给它的变量有一个名称,但该函数没有)。这可能会使调试更加困难(查看断点列表或调用堆栈),尽管现代调试器在显示变量名称(如果函数没有)时会很好。

注意,因为他们不是一步一步的代码的一部分,你不能声明控制结构中使用的函数:

function foo() { 
    if (condition) { 
     function bar() { /* ...do something... */ }  // <==== WRONG 
    } 
    else { 
     function bar() { /* ...do something else... */ } // <==== WRONG 
    } 
} 

这是原因之一,我们有功能表达式

function foo() { 
    var bar; 

    if (condition) { 
     bar = function() { /* ...do something... */ };  // <==== Right 
    } 
    else { 
     bar = function() { /* ...do something else... */ }; // <==== Right 
    } 
} 

注意一些JavaScript引擎容忍上面的错误的语法,但方式他们tolera它因发动机而异。一些引擎将声明转换为表达式。其他人总是使用第二个声明。只是不要这样做。 :-)

最后:还有一种叫做名为函数表达式:

var x = function foo() { /* ... */ }; 

函数有一个名称(foo),变量引用它有一个名字(x)。这是一个表达式,因为它被用作右边的值(=的右边,初始值设定中的:,如果您将它作为参数传递给函数等等)。不幸的是,各种JavaScript引擎已经知道以各种不同的方式获得NFE(因为他们被称为)是错误的,尽管我认为在当今世界,它只是IE8和更早的版本,其中create two different functions at different times

+0

TJ,谢谢你的真棒解释,你是对的,我只是懒惰的隐式全局变量,但实际上,我不想这样做。 – 4m1r

0

作为执行的匿名函数(隐藏);

var objOuter = (function(){ // Anonymous Function 
    var funcPrivate = function() { 
     // private function contents 
    }; 
    var funcPublic = function() { 
     // private function contents 
    }; 

    return { // JavaScript Object 
     funcName : funcPublic // provides public access to funcPublic 
    }; 
})(); 

//objOuter.funcPrivate(); // Failure, private. 
//objOuter.funcPublic(); // Failure, internal name for public function. 
objOuter.funcName(); // Executes funcPublic in objOuter's scope. 

作为JavaScript对象定义的一部分(一切是公共的):

var objOuter = { // JavaScript Object 
    funcName : function() { 
     // function contents 
    } 
}; 

objOuter.funcName();  // Executes funcName 

匿名函数被执行的JavaScript代码,但{}为JavaScript对象定义的内部是一个不同类型的的配对键和值的语法。

在JavaScript对象内部,您将值function()指定给密钥funcName。当您引用该密钥并通过传递参数列表()来执行该密钥时,该函数将执行。

在匿名函数(也称为Revealing Module Pattern)中,您正在模块范围内定义私有函数,然后将这些函数的引用作为返回的JavaScript对象的一部分传递给调用代码。

+0

@ T.J.Crowder我想JavaScript对象表示法和JavaScript对象表示法(JSON)是有区别的。我更新了它。 – Corion

+1

@科里昂:确实如此。 :-) [JSON](http://json.org)是JavaScript对象初始化程序语法的一个子集。 –

0

variableName : value语法只能用于对象的上下文中。例如:

var obj = { 
    z: function(){return 'this is z'}; 
}; 

在这种情况下,运行obj.z()将返回This is an object
在你的情况下,你只是在一个函数的上下文中,而不是声明一个对象。这意味着您必须使用与xy一起使用的语法。

0

冒号表示法仅适用于对象语法。

例如

var theObj = {one : 'one', two : 'two'}; 

为了添加到对象中要使用点符号:

theObj.three = 'three'; 
相关问题