1.函数声明和函数表达式有什么区别
- 函数声明后面的分号可加可不加,不影响接下来的语句,但是函数表达式后面没有分号结束,js引擎则会认为后面的内容仍是函数表达式的一部分
//没加分号报错
var a = function(){}console.log("")
//没加分号不报错
function b(){}console.log("")
- 变量提升时,函数声明将作为整个代码块一起提升至作用域的最上面;函数表达式则是提升变量
//提升变量var a
var a = function(){};
//提升函数function fn(){}
function fn(){};
2.什么是变量的声明前置?什么是函数的声明前置
JavaScript的解析代码时存在变量提升机制,具体流程是JS解析器在预执行(解析)阶段先会将所有的变量声明提升至该作用域的最顶部,然后在进行解析其余的代码
这一机制同样适用于函数的声明,只不过函数声明的提升是将整个代码块一并提升
3.arguments 是什么 (*)
我们知道函数可以添加参数,而arguments对象包含了函数运行时的所有参数,但这个对象只能在函数体内部使用。
function fn(a,b,c,d){
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
console.log(arguments[3]);
}
fn(1,2,3,4);//1 2 3 4
//使用arguments.length属性得知参数的个数
function fn2(){
console.log(arguments.length);
}
fn2(1,2,3,4)//4
4.函数的重载怎样实现
什么是重载函数
允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数必须不同,这就是重载函数。重载函数的作用
重载函数常用来实现功能类似而所处理的数据类型不同的问题。-
JS的函数重载的实现
在面向对象语言里重载是很重要的一个特性,而JavaScript这个自称面向对象的语言是没有直接提供重载。那么JavaScript是怎么实现(准确地讲应该叫“模拟”)的呢?
利用arguments实现重载
arguments是JavaScript里的一个内置对象,包含了调用者传递的实际参数,而调用时只它和数组一样有个length属性;
我们暂且把它当“数组”来理解吧,我们根据该数组的长度以及其元素的类型来选择不同的实现,从而模拟了重载。
给个例子:
function getDate(){
if(arguments.length==0){
var date=new Date().toLocaleDateString();
return "您没有输入参数,现在时间:"+date ;
}
if(arguments.length==1){
if(arguments[0].constructor ==Date){
return "您输入的参数是Date类型,现在时间是:"+arguments[0].toDateString();
}
if(arguments[0].constructor ==String){
return "您输入的参数是String类型,现在时间是:"+arguments[0];
}
}
}```
于是我们可以这样调用:
getDate()
getDate(newDate())
getDate("星期一")```
**这样就实现了JavaScript的重载!**
#### 4.立即执行函数表达式是什么?有什么作用
- **什么是立即执行函数**
一种声明之后就立即进行该函数执行操作的函数
- **立即执行函数的写法**
function()前面加任意符号,告诉js引擎这是要执行函数而不是声明函数,注意最后必须加分号
写法1:
(function fn(n){
console.log(n)
}());
写法2:
!function (){
}();
- **为什么要用立即执行函数**
- 消除全局变量的污染;
- 防止其他js文件出现与本文件的函数名重名情况,那么函数内部定义的 同一个变量a有可能被污染;
- IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量
#### 5.什么是函数的作用域链
作用域是指变量存在的范围,可分为全局作用域和函数作用域,由此可划分变量为全局变量和局部变量
- 全局作用域:变量作用范围是全局,直到js运行失效
- 函数作用域:变量作用分为是函数内部,函数执行完后就失效
- 作用域链:JavaScript语言特有的”链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量
var a = 1;
function fn(){
var b = 2;
c=3;
console.log(a+b)
}
b//b is not defined
//a是全局变量,只要js运行都会生效;
//b是局部变量,只在函数体内部生效;
//注意如果函数内部的变量不加var声明,那么会当做全局变量
#### 6.以下代码输出什么?
![](http://upload-images.jianshu.io/upload_images/1993435-e9b059bb0899a1b4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
//getInfo('hunger', 28, '男');
name: hunger
age: 28
sex: 男
["hunger",28,"男"]
name: valley
//getInfo('hunger', 28);
name: hunger
age: 28
sex: undefined
["hunger",28]
name: valley
//getInfo('男');
name: 男
age: undefined
sex: undefined
["男"]
name: valley
#### 7.写一个函数,返回参数的平方和
![](http://upload-images.jianshu.io/upload_images/1993435-06ecb010fd130579.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
//这段函数实现的需求是:
若输入的参数不是数值,则返回"输入值" is Not a number,接着会去计算那些数值项
function sumOfSquares(x,y,z){
var argu,sum=0;
for(i=0;i<fn.length;i++){
if (typeof arguments[i] !== "number") {
console.log(arguments[i]+" " + "is Not a number!")
} else {
argu = Math.pow(arguments[i],2)
sum += argu;
}
}
console.log(sum);
}
sumOfSquares(1,3,9)//91
sumOfSquares(1,3)//undefined is not a number 5
####8. 如下代码的输出?为什么
![](http://upload-images.jianshu.io/upload_images/1993435-4b48c65a66917034.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
undefined
ReferenceError: b is not defined
分析:
上面的代码可以写成,
var a;
console.log(a);
a=1;
console.log(b);
由于变量提升的缘故,变量a提升至作用域的最前面,所以第1个输出为undefind;
第2个输出的变量b由于没有进行变量声明,所以出现ReferenceError:b is not defined;
####9.如下代码的输出?为什么
![](http://upload-images.jianshu.io/upload_images/1993435-0933d45acde678da.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
hello world
"error"
"TypeError: sayAge is not a function
分析:
这里使用函数声明和函数表达式分别定义两个函数sayName()和sayAge();
在js引擎实际解析代码时,使用函数声明方法生命的sayName()会整个代码块提升至作用域顶部,而使用函数表达式定义的sayAge()则只会讲var sayAge提升至顶部;
由此一来,造成上面两个函数在调用时,sayName()能够调用成功,而sayAge()则因为js引擎无法识别其为函数类型而报错
####10.如下代码的输出?为什么
![](http://upload-images.jianshu.io/upload_images/1993435-7ded7b9459ed38f4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
上述代码等价于:
function fn(){}
var fn;
fn=3;
console.log(fn);
//3
同一个作用域内,变量和方法的命名相同,变量的赋值会覆盖方法的赋值,不论它们的顺序是怎样。
####11.如下代码的输出?为什么
![](http://upload-images.jianshu.io/upload_images/1993435-3a77c15d47be2091.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
function fn2(){
console.log('fnnn2');
}
3
function fn(fn2){
console.log(fn2);
var fn2 = 3;
console.log(fn2);
console.log(fn);
function fn2(){
console.log('fnnn2');
}
}
1.通过fn(10)调用函数fn,此时变量fn2=10;
2.console.log(fn2)输出fn2的整个函数定义内容;
3.fn2=3,然后执行console.log(fn2)操作而输出3;
4.console.log(fn)输出fn的整个函数定义内容;
####12.如下代码的输出?为什么
![](http://upload-images.jianshu.io/upload_images/1993435-456e769e4bcc996d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
输出结果:
TypeError: fn is not a function
上述代码等价于:
var fn;
function fn(fn){
console.log(fn);
}
fn=1;
console.log(fn(fn));
此时,当变量名与函数名重名时,后出现的变量值会覆盖函数内容,只会把fn当做变量看待而不是函数,所以js引擎报错
####13.如下代码的输出?为什么
![](http://upload-images.jianshu.io/upload_images/1993435-6c5f88f714477000.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
输出结果:
undefined
undefined
10
100
上述代码等价于:
var i;
var j;
console.log(j);
console.log(i);
for(var i=0; i<10; i++){
var j = 100;
}
console.log(i);
console.log(j);
1.变量提升机制使得var i,j提升至作用域顶部;
2.console.log(j)和console.log(i)输出结果均为undefined;
3.for语句循环10次后退出循环,此时i=10,j=100;
####14.如下代码的输出?为什么
![](http://upload-images.jianshu.io/upload_images/1993435-b536a067b0a2fd80.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
输出结果:
undefined
100
10
上述代码等价于:
var i;
var fn;
function fn(){
console.log(i);
var i = 99;
fn2();
console.log(i);
function fn2(){
i = 100;
}
}
fn();
i=10;
fn=20;
console.log(i);
1.变量提升后,调用函数fn;
2.此时i为赋值,所以console.log(i)为undefined;
3.调用函数fn2,在fn作用域下返回全局变量i=100,所以执行第2个console.log(i)时显示100;
4.最后i=10,执行第3个console.log(i)时显示10;
####15.如下代码的输出?为什么
![](http://upload-images.jianshu.io/upload_images/1993435-d2be7971dcca080a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
输出结果:
10
9
8
7
6
5
4
3
2
0
上述代码等价于:
var say;
//立即执行函数
(function say(n){
console.log(n);
if(n<3) return;
say(n-1);
}( 10 ));
say=0;
console.log(say);
1.执行立即执行函数,先输出原始参数10,然后执行判断语句,不符合条件语句后再次调用say()函数进行递归,直至参数n小于3后跳出函数体,期间输出值为10,9,8,7,6,5,4,3,2
2.执行console.log(say),输出值为10