声明前置和作用域也是JS 部分面试常考点
1.函数声明和函数表达式有什么区别
函数声明:使用function关键字可以声明一个函数。
function sayHello(){
console.log('hello')
}
//函数调用
sayHello()```
声明不必放到调用的前面,声明的是一个函数,用时就是调用,该声明位置可放在后面。函数声明最重要的特征就是函数声明提升,意思是在执行代码之前就会读取函数声明。
函数表达式:用函数表达式定义的函数在使用之前必须先赋值。
```var sayHello = function(){
console.log('hello');
}
sayHello()```
声明必须放到调用的前面,声明的是一个变量,必须声明过后才能使用。
####2.什么是变量的声明前置?什么是函数的声明前置
- 变量的声明前置:JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,然后给他初始值undefined,然后才逐句执行程序,这就叫做“变量提升”,也即“变量的声明前置”。在一个作用域块中,所有的变量都被放在块的开始出声明,但是变量的赋值不会提升。
- 函数的声明前置:在一个作用域下,同var 声明的变量一样,function 声明的函数也会前置。函数的声明前置优先级高于变量的声明前置。
```console.log(a);
var a = 3;
console.log(a);
sayHello();
function sayHello(){
console.log('hello');
}```
执行时语句顺序如下:
```var a
function sayHello(){}
console.log(a);//undefined
a=3
console.log(a); //3
sayHello();```
####3.arguments 是什么
arguments 是一个类似数组的对象, 对应于传递给函数的参数。在函数内部,可以使用arguments对象获取到该函数的所有传入参数。arguments 对象仅在函数内部有效,在函数外部调用 arguments 对象会出现一个错误。
严格模式下,
1. arguments 不能通过程序语法被绑定(be bound)或赋值。
2.函数的 arguments 对象会保存函数被调用时的原始参数。arguments[i] 的值不会随与之相应的参数的值的改变而变化,同名参数的值也不会随与之相应的 arguments[i] 的值的改变而变化。
3.不再支持 arguments.callee。arguments.callee 是一个不可删除属性,而且赋值和读取时都会抛出异常。
``` function printPersonInfo(name, age, sex){
console.log(name);
console.log(age);
console.log(sex);
}
可以写为
function printPersonInfo(){
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
}```
####4.函数的"重载"怎样实现
在 JS 中没有重载,同名函数会覆盖。 但可以在函数体针对不同的参数调用执行相应的逻辑。
```function printPeopleInfo(name, age, sex){
if(name){
console.log(name);
}
if(age){
console.log(age);
}
if(sex){
console.log(sex);
}
}
printPeopleInfo('Byron', 26);
printPeopleInfo('Byron', 26, 'male');```
####5.立即执行函数表达式是什么?有什么作用
立即执行函数通常有下面几种写法:
```(function fn0() {})();
(function fn1() {} ());
// 在数组初始化器内只能是表达式
[function fn2() {}];
// 逗号也只能操作表达式
1, function fn3() {};```
在Javascript中,一对圆括号“()”是一种运算符,跟在函数名之后,表示调用该函数。比如,print()就表示调用print函数。
作用:
一是不必为函数命名,避免了污染全局变量;
二是隔离作用域,IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量。
####6.求n!,用递归来实现
```function fn1(i){
if(i===1){
return 1;
}
return i*fn1(i-1);
}```
####7.以下代码输出什么?
```function getInfo(name, age, sex){
console.log('name:',name);
console.log('age:', age);
console.log('sex:', sex);
console.log(arguments);
arguments[0] = 'valley';
console.log('name', name);
}
getInfo('饥人谷', 2, '男');
getInfo('小谷', 3);
getInfo('男');```
输出:
name:饥人谷 age:2 sex:男 ['饥人谷',2,'sex'] name valley
name:小谷 age:3 sex:undefined ['小谷',3] name valley
name:男 age:undefined sex:undefined ['男'] name valley
####8. 写一个函数,返回参数的平方和?
```function sumOfSquare() {
var result = 0;
for(var i=0; i<arguments.length; i++){
result+=arguments[i]*arguments[i];
}
return result;
}
var result = sumOfSquares(2,3,4)
var result2 = sumOfSquares(1,3)
console.log(result) //29
console.log(result) //10```
####9. 如下代码的输出?为什么
```console.log(a);
var a = 1;
console.log(b);```
输出:
undefined /*因为变量声明前置,var a,console.log(a)*/
b is not defined报错 /*因为变量b没有声明*/
####10. 如下代码的输出?为什么
```sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};```
输出:
hello world /*函数声明可以放在后面*/
sayAge is not a function报错 /*声明放在后面了变量没定义,声明必须放到调用的前面,声明的是一个变量,必须声明过后才能使用*/
####11. 如下代码输出什么? 写出作用域链查找过程伪代码
```var x = 10
bar()
function foo() {
console.log(x)
}
function bar(){
var x = 30
foo()
}```
输出:10
```globalContext{
AO:{
x:10
foo:function
bar:function
},
Scope:null
}
foo.[[scope]] = globalContext.AO
bar.[[scope]] = globalContext.AO
barContext{
AO:{
x:30
},
Scope:bar.[[scope]] //globalContext.AO
}
fooContext{
AO:{
},
Scope:foo.[[scope]] // globalContext.AO
}```
####12. 如下代码输出什么? 写出作用域链查找过程伪代码
```var x = 10;
bar()
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}```
输出:30
```globalContext{
AO:{
x:10
bar:function
},
Scope:null
}
foo.[[scope]] = barContext.AO
bar.[[scope]] = globalContext.AO
barContext{
AO:{
x:30
foo:function
},
Scope:bar.[[scope]] //globalContext.AO
}
fooContext{
AO:{
},
Scope:foo.[[scope]] // barContext.AO
}```
####13. 以下代码输出什么? 写出作用域链的查找过程伪代码
```var x = 10;
bar()
function bar(){
var x = 30;
(function (){
console.log(x)
})()
}```
输出:30
```globalContext{
AO:{
x:10
bar:function
}
Scope:null
}
bar.[[scope]] = globalContext.AO
barContext{
AO:{
x:30
}
Scope:bar.[[scope]]
}```
####14. 以下代码输出什么? 写出作用域链查找过程伪代码
```var a = 1;
function fn(){
console.log(a)
var a = 5
console.log(a)
a++
var a
fn3()
fn2()
console.log(a)
function fn2(){
console.log(a)
a = 20
}
}
function fn3(){
console.log(a)
a = 200
}
fn()
console.log(a)```
输出:
undefined
5
1
6
20
200
```globalContext{
AO:{
a:200
fn:function
fn3:function
},
Scope:null
}
fn.[[scope]] = globalContext.AO
fn2.[[scope]] = fnContext.AO
fn3.[[scope]] = globalContext.AO
fnContext{
AO:{
a:20
fn2:function
},
Scope:fn.[[scope]] //globalContext.AO
}
fn2Context{
AO:{
},
Scope:fn2.[[scope]] // fnContext.AO
}
fn3Context{
AO:{
},
Scope:fn3.[[scope]] // globalContext.AO
}```