脚本宝典收集整理的这篇文章主要介绍了译: 函数提升与提升面试的相关问题,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
作者关于提升的话题,总共有两篇。(后来又有一个讨论篇),再次搬过来。水平有限,如果翻译的不准确请包涵,并去看原文。下面开始:@H_304_2@
这是我之前的关于“提升”的文章,标题为《用let,const来指导你的JavaScript变量提升》(中/英)的第二部分。因此在深入研究之前,请确保你已经阅读过第一部分。
之前我只讨论过变量提升,是因为函数提升在JavaScript中与变量提升不同。它有自己的独特方式。我将在这对函数进行扩展,以及在面试中面试官总会提问的“提升”(变量和函数)的棘手问题。
希望通过完成这两部分,你能真的在你的JavaScript检查清单中划掉它。
让我们开始吧。
函数提升
在JavaScript里有两种方式创建函数,通过函数声明和函数表达式。那就看看这两种方式是如何影响“提升”的。
函数声明
用指定的参数来定义函数。
语法:
function name(param1, param2, ...) {
[statements]
}
在JavaScript里,函数声明提升函数定义。
因此,这些函数在被声明之前便可以使用。
例子:
hoisted() // output: "Hoisted"
function hoisted() {
console.LOG('Hoisted')
}
下面的例子,展示JavaScript编译器如何看待上面的代码:
// Hoisted code
function hoisted() {
console.log('Hoisted')
}// Rest of the code
hoisted() // output: "Hoisted"
如果你在全局作用域或者功能区作用域(在JavaScript里基本叫局部作用域)进行函数声明,这个行为是真实的。
这非常有用,因为你能在代码开头使用高级逻辑,使其可读与可理解。
提示:不要在“if/else”中进行函数声明。
函数表达式
“function”关键字也能在一个表达式中定义一个函数。
语法:
const myFunction = function [name](param1, param2, ...) {
[statements]
}
函数名是可选的,因此可以是匿名函数。我们可以用箭头函数,如下所示:
const myFunction = (param1, param2, ...) => {
[statements]
}
在JavaScript里,函数表达式没有被提升。
因此,你不能使用函数表达式在定义它们之前。
例子:
notHoisted() // TyPEError: notHoisted is not a function
const notHoisted = function() {
console.log('foo')
}
关于函数创建中“提升”的部分,以上所有这些都要记住。
现在来看看面试问题!
“提升”面试问题
“提升”的不稳定行为一直是面试过程中的热门问题。用之前和现在这两篇文章的知识,可以解答这个话题中的任何问题。
问题 1 :
VAR a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
console.log(a);
输出: 1, 这是为什么?! ?
这是因为“function a() {}”声明被创建在“函数/局部”作用域中。这个新“a”函数在声明和定义的时候被提升到它的封闭函数b的顶端。下面演示发生了什么:
var a = 1;
function b() {
// Hoisted
function a() {}
a = 10;
return;
}
b();
console.log(a)
因此,赋值a=10;不能改变全局作用域a的值,任然是1,而是将局部a从函数改为整数10。
如果声明函数a不在这,那将输出10。
问题 2:
function foo(){
function bar() {
return 3;
}
return bar();
function bar() {
return 8;
}
}
alert(foo());
输出:8
两个bar都是用函数声明的函数,将被提升到foo的局部作用域顶端。
然而,返回8的bar()将晚于第一个返回3的提升。因此,这个返回8的函数将被执行。
之后的场景:
function foo(){
//Hoisted before
function bar() {
return 3;
}
// Hoisted after
function bar() {
return 8;
} return bar();
}
alert(foo());
问题 3:
function parent() {
var hoisted = "I'm a variable";
function hoisted() {
return "I'm a function";
}
return hoisted();
}
console.log(parent());
输出:“类型错误:hoisted不是一个函数”
这个很诡异。函数 vs 变量!我们来分析下。
我们都知道,说到变量提升,只有声明被提升(值是“undefined”),而不是定义!
如果是函数声明的方式声明函数,声明和定义一并提升!
现在,如果是多个相同标识符声明(变量和函数在同一作用域里)这样的情况,这个变量的提升会直接忽略。
解释器只声明函数并提升它。
最终,这个声明变量变量赋值被执行(没有被提升),且值分配给了被提升的函数,值“I‘m a variable” ,
这是一个简单的字符串而不是函数。于是报错了!
这后面的场景重现了问题:
function parent() { // Function declaration hoisted with the definition
function hoisted() {
return "I'm a function";
} // Declaration ignored, assignment of a string
hoisted = "I'm a variable";
return hoisted();
}
console.log(parent());
问题 4:
alert(foo());
function foo() {
var bar = function() {
return 3;
};
return bar();
var bar = function() {
return 8;
};
}
输出:3
这个简单。函数foo()本身将作为函数声明在全局范围内提升。在函数foo里面,是两个明确的函数表达式的例子。
编译器不会提前读取第二个函数bar() (没有提升)。第一个将被执行并返回。
问题 5:
var myVar = 'foo';(function() {
console.log('Original value was: ' + myVar);
var myVar = 'bar';
console.log('New value is: ' + myVar);
})();
输出: “Original value was: undefined”, “New value is: bar”
在这个例子中,全局变量myVar的值‘foo’出现在Picture之外。这是因为变量myVar在函数作用域内部声明和定义,而且被提升到了IIFE的顶端,值是‘undefined’,他被首先记录。然后将值“bar”分配并记录下来。
这是我这里对JavaScript提升的总结。?
如果你想学习箭头函数和ES6其他相关的功能,请查看下面的文章。
Peace ✌️
至此,关于提升的两篇文章结束了。后来一个读者和作者就问题1和问题3产生了分歧。到时候也搬过来吧。
以上是脚本宝典为你收集整理的译: 函数提升与提升面试的相关问题全部内容,希望文章能够帮你解决译: 函数提升与提升面试的相关问题所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。