如果我们有
var randomname = {};
randomname.attribute = 'something';
function randomname(){
alert(randomname.attribute);
}
randomname();
Run Code Online (Sandbox Code Playgroud)
javascript会抛出任何错误吗?
为什么是这样?
javascript是否应该通过您调用它的方式告诉您的内容?
CMS*_*CMS 19
它应该给你一个TypeError例外 - 试图调用一个对象 - 在Firebug的控制台中观察到的行为是不正确的......
FunctionDeclaration将它们提升到其封闭范围的顶部,您的代码实际上按以下顺序执行:
// FunctionDeclaration is hoisted
function randomname(){
alert(randomname.attribute);
}
// the var has no observable effect, because
// the randonmane identifier is already defined
randomname = {};
randomname.attribute = 'something';
randomname(); // TypeError, randomname is not callable.
Run Code Online (Sandbox Code Playgroud)
当进入执行上下文时,变量实例化过程(也就是ES5中的声明绑定实例化)定义了激活对象上的属性(AO,这是一个不可到达的对象,它在本地保存变量,函数声明和函数参数的标识符.范围)按以下顺序:
FormalParameterList标识符(用于功能代码)FunctionDeclaration 身份标识VariableDeclaration 身份标识A VariableDeclaration不会覆盖标识符已经在AO中定义(例如,通过前两个步骤之一),但是赋值将在运行时完成.
例如:
(function (foo) {
var foo; // doesn't affect the existing `foo` identifier
return typeof foo;
function foo () {}
})('string'); // yields "function"
Run Code Online (Sandbox Code Playgroud)
但是,如果进行了赋值,则将替换标识符的值,例如:
(function (foo) {
var foo = {};
return typeof foo;
function foo () {}
})('string'); // yields "object"!!
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,当调用函数时, - 但在代码执行之前 - 在foo激活对象(也称为变量对象)上设置标识符.
首先为它分配形式参数的值'string',值,然后FunctionDeclaration检查函数体上的所有函数,foo找到一个名为的函数,然后foo标识符将指向该函数.
之后,检查所有变量声明,我们有一个带有标识符的变量声明foo,但是在这个时间内它的值被认为是 - 该函数尚未执行 - .
此时,该函数已准备好执行,其词法和可变环境已设置.
将在函数中执行的第一件事是赋值foo = {};,它取代了我们之前使用的函数的引用.
为什么它在其他浏览器和Firefox上表现不同?
因为:
由于Firebug通过在with语句中包装来评估代码,因此这将导致FunctionDeclaration在语句上下文中评估-a Mozilla的函数语句.
要显示Function语句在Mozilla实现上的行为,请考虑以下示例:
if (true) {
function foo () { return 'true!';}
} else {
function foo () { return 'false??!';}
}
foo();
Run Code Online (Sandbox Code Playgroud)
在Mozilla中你会得到'true!',而在其他实现中你会得到'false??!'- 甚至在IE-上.
这是因为函数定义是在运行时,在Statement上下文中(在真正的分支中if),而在其他实现中,函数声明是在分析时计算的.
上面的例子实际上应该SyntaxError在任何实现上产生异常,但是它们中的任何一个都不会发生......
FunctionDeclaration应该只允许在全局代码中或直接在函数的FunctionBody中使用A.
一个很多 人交替使用条款函数声明和函数的声明,但是这是完全错误的,ECMAScript中没有定义函数语句,是一个非标准的功能.
该规范简要说明了这个问题:
注意:已知几种广泛使用的ECMAScript实现支持将FunctionDeclaration用作Statement.然而,在应用于此类FunctionDeclarations的语义中的实现之间存在显着且不可调和的变化.由于这些不可调和的差异,使用FunctionDeclaration作为Statement会导致代码在实现中无法可靠地移植.建议ECMAScript实现不允许使用FunctionDeclaration,或在遇到此类用法时发出警告.ECMAScript的未来版本可以定义用于在Statement上下文中声明函数的替代可移植方法.
尝试在全局执行上下文中运行代码 - 在一个简单的<script>元素中 - 你会看到它在Firefox上崩溃:
<script type="text/javascript">
var randomname = {};
randomname.attribute = 'something';
function randomname(){
alert(randomname.attribute);
}
randomname();
</script>
Run Code Online (Sandbox Code Playgroud)
你可以在这里找到上面的例子,确保打开Firebug的控制台,你会看到你在其他浏览器上遇到的同样的错误.
函数实际上也是 JavaScript 中的一个对象(第一类对象)。
所以你可以做这样的事情。
var human = function(){
alert("Hi");
};
// which is perfectly normal
//but then
human.name="Anubhav";
Run Code Online (Sandbox Code Playgroud)
然后你可以执行以下操作:
human();//works
alert(human.name);//works
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5026 次 |
| 最近记录: |