在以下示例中,为什么'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());
})();
在以下示例中,为什么'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());
})();
...为什么 'Z' 的声明导致语法错误?
因为您在对象初始值设定项之外使用属性初始值设定项语法。
这是一个对象初始化(位开始{
与}
结尾)包含属性初始化(中线):
var obj = {
propertyName: "property value"
};
所以,如果你声明一个对象,你可以用你的z
线(不;
):
var obj = {
z: function() { return 'this is z'}
};
但是,你必须在你的代码,你在一个对象初始化不是,你在一个函数体是。所以你不能使用这种语法。
值得注意的是,您的x
和y
是完全不同的结构。
此:
function x(){return 'this is x'};
是一个功能声明。函数声明在包含函数中的任何逐步代码运行之前进行处理,并且函数名称位于包含函数顶部的范围内。 (有时人们称之为 “冲顶”。)
此:
y = function(){return 'this is y'};
是一个功能表达。它与所有表达式一样,在包含函数中逐步执行代码时遇到。
(代码所引用的瀑布猎物The Horror of Implicit Globals,顺便说一句:既然在上y
没有var
,既然你不使用严格模式,该行创建了一个全球变量称为y
。)
在自执行函数中声明函数的正确方法是什么?
无论是书(x
或y
形式)比其他的更正确的(撇开隐性的全球事情)。他们每个人都有使用,这取决于你在做什么。 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。
TJ,谢谢你的真棒解释,你是对的,我只是懒惰的隐式全局变量,但实际上,我不想这样做。 – 4m1r
作为执行的匿名函数(隐藏);
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对象的一部分传递给调用代码。
@ T.J.Crowder我想JavaScript对象表示法和JavaScript对象表示法(JSON)是有区别的。我更新了它。 – Corion
@科里昂:确实如此。 :-) [JSON](http://json.org)是JavaScript对象初始化程序语法的一个子集。 –
variableName : value
语法只能用于对象的上下文中。例如:
var obj = {
z: function(){return 'this is z'};
};
在这种情况下,运行obj.z()
将返回This is an object
。
在你的情况下,你只是在一个函数的上下文中,而不是声明一个对象。这意味着您必须使用与x
或y
一起使用的语法。
冒号表示法仅适用于对象语法。
例如
var theObj = {one : 'one', two : 'two'};
为了添加到对象中要使用点符号:
theObj.three = 'three';
因为你不在对象范围内的语法明智... – CBroe
你为什么会想到上班? – SLaks
有道理,所以我想简短的答案是一个函数(匿名或命名)不支持属性声明?感谢您的出色答复。 – 4m1r