让我学习Javascript的函数和函数表达式。

让我学习Javascript的函数和函数表达式。
1。函数声明和函数表达式

在ECMAscript,最常用的两种方法创建一个函数是一个函数的表达式和函数的声明,这两个时期之间的差异是有点晕,因为ECMA规范只明确了一点:函数的声明必须有标识符(标识符)(即我们常说的函数名称),你可以省略函数表达式中的标识符:

函数声明:函数函数名(参数:可选){函数体}

函数表达式:函数函数名(可选)(参数:可选){函数体}

所以我们可以看到,如果我们不声明函数名,它必须是一个表达式。如果我们声明函数的名称,我们怎么说它是函数声明或函数表达式ECMAscript是语境的区别,如果函数(Foo){ }是一个赋值作为它的一部分,它是一个函数表达式,如果函数(Foo){ }是包含在身体的一个函数,或是在上面,它是一个函数声明。
函数,因为它是程序的一部分
var(=){函数;因为它是赋值的一部分

新函数(bar){ };表达式,因为它是一个新表达式

(函数(){())
函数(bar){语句,因为它是函数体的一部分。
});

表达和陈述有很细微的差别,首先,任何表达函数的声明进行评估之前,解析、分析和评估,即使在最后一行代码你的声明,它将在第一个表达式的分析/评估是在相同的范围内,参考下面的例子,函数fn是警示语句之后,但当警报,FN被定义:
警报(FN());

函数FN(){
return'hello世界!;
}

此外,还需要提醒您,在函数声明语句中,虽然可以使用条件,但是没有被标准化,也就是说不同的环境可能有不同的结果,所以本例中,最好使用函数的概念:因为条件语句中没有块作用域。
/不要这样做!
因为函数的一些浏览器将返回第一,一些浏览器返回是第二个。

如果(真){
函数(){
return'first;
}
}
{其他
函数(){
return'second;
}
}
(食品);

但是,这种情况下,我们必须使用函数表达式
变量Foo;
如果(真){
函数(){
return'first;
};
}
{其他
函数(){
return'second;
};
}
(富);

函数声明的实际规则如下:

一个函数声明只能出现在一个程序或功能。根据这项条款,他们不能出现在块(block)({…}),例如,不能出现在一个如果,虽然,或声明。因为块(块)只能包含一个表,它不能包含源等要素的函数声明。另一方面,如果我们仔细看看,规则也会发现让表达出现在块的唯一途径(块)是使它的表达语句的一部分。然而,该规范明确指定一个表达式语句不能开始关键词功能。事实上,函数表达式不能同时出现在声明语句或块(块),因为块(块)是由语句结束。

2,命名函数表达式

提到命名函数表达式,理应是它的名字,无功吧,前面的例子(foo =功能){ };是一个有效的命名函数表达式,但它是记住这个名字只有在规范中定义的功能范围是有效的重要的,因为在效果的有效域外围的指定标识符不能:
函数(){
返回: / /函数foo;——> foo的范围内是有效的
};
外部不可见
类型 / /定义foo;
(f);

那么,命名法有什么用呢你为什么要被点名

正如我们在开始时所说的,给它一个名字是因为它可以使调试过程更加方便,因为在调试过程中,如果调用堆栈中的每个项目都有自己的名称来描述,那么调试过程就太酷和不同了。

小贴士:这里提出一个小问题:在沙三、范围对象名称的函数表达式的object.prototype.this继承的属性意味着只是命名函数表达式也会介绍所有的属性在Object.prototype的范围。结果可能是意想不到的。
函数(){返回null;}
函数f(){
返回construcor();
}
f(); / / {三环境}

程序看起来像它会产生无效,但它实际上会产生一个新的对象。因为有名函数表达式继承了Object.prototype.constructor(即对象的构造函数)范围内。如有声明,这个范围将由动态变化的影响object.prototype.fortunately,ES5纠正错误

这种行为一个合理的解决方案是创建一个局部变量同名的函数表达式和赋值为空。即使在环境里的函数表达式声明没有提出错误,VAR重新声明变量确保变量G仍然难免会设置变量g。为确保复制功能可以回收。
函数g(){
返回17;
}
var = null;

三.调试器中的命名函数表达式(调用堆栈)

刚才,一个命名函数表达式的真正用法是调试,它是如何使用的如果一个函数有一个名字,调试器将显示它的名字调用堆栈上的时候是调试。一些调试器(萤火虫)有时你的名字和显示的功能,让他们和那些使用具有相同的作用,但通常的便利功能,调试安装简单规则的名字,所以没有太多价值,我们来看一个例子:没有命名的函数表达式
函数(){
返回条();
}
函数条(){
Baz()返回;
}
函数的Baz(){
调试器;
}
(食品);

在这里我们使用3个名称函数声明
所以当走到调试器/调试语句,调用堆栈上的萤火虫看起来很清楚
因为它很清楚
巴兹
酒吧
Foo
expr_test.html()
调用堆栈的信息,我们可以清楚地知道foo调用酒吧,酒吧叫Baz(Foo在expr_test.html文件,在全球范围内被称为然而,)有一个相对凉爽的地方,据说它被命名为一个匿名函数表:
函数(){
返回条();
}
函数(){()
Baz()返回;
}
函数的Baz(){
调试器;
}
(富);

调用堆栈
巴兹
(bar)
Foo
expr_test.html()

然后,当函数表达式稍微复杂一些时,调试器就不那么聪明了,我们只能在调用堆栈中看到问号。
函数(){
返回条();
}
var =(函数(){())
如果(窗口。addEventListener){
返回函数(){
Baz()返回;
};
}
如果(窗口。attachevent){
返回函数(){
Baz()返回;
};
}
});
函数的Baz(){
调试器;
}
(富);

调用堆栈
巴兹
(())这是一个问号,哦,显示为匿名函数(匿名函数)
Foo
expr_test.html()

另外,当一个函数被赋值给多个变量时,会有一个令人沮丧的问题。
函数(){
Baz()返回;
}
函数(){()
调试器;
};
Var Baz =吧;
函数(){
警报(欺骗);
};
(食品);

调用堆栈:
(酒吧)
Foo
expr_test.html()

此时,调用堆栈显示富调用条,但实际情况并非如此。这样做的原因是,Baz已经与另一个函数的引用和交换包含警报(伪造的)。

归根结底,只有函数表达式的名称是最委托的方法,即使用命名函数表达式。让我们使用一个具有名称的表达式重写上面的示例(注意在立即调用的表达式块中返回的2个函数的名称是bar):
函数(){
返回条();
}
var =(函数(){())
如果(窗口。addEventListener){
返回函数条(){
Baz()返回;
};
}
如果(窗口。attachevent){
返回函数条(){
Baz()返回;
};
}
})();
函数的Baz(){
调试器;
}
(富);

再次清楚地看到调用堆栈信息!
巴兹
酒吧
Foo
expr_test.html()
好的,在整篇文章的最后,我们将更接近Javascript。我希望您会喜欢这篇文章,您会越来越感兴趣,并继续关注我从Javascript中学到的一系列文章。
免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部