1、函数声明和函数表达式有什么区别
函数声明和函数表达式都有声明前置的效果,但是:
-
函数表达式的声明前置效果更像变量的声明前置效果,相当于只是一个变量名被前置了,而这个变量的值并没有被前置,不能在前面调用,会报错。
-
函数声明则相当于整个函数都被前置了,可以在声明之前调用。
2、什么是变量的声明前置?什么是函数的声明前置
-
什么是变量的声明前置?
JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,然后给他初始值undefined,然后才逐句执行程序,这就叫做“变量提升”,也即“变量的声明前置”。
-
什么是函数的声明前置?
和变量的声明会前置一样,函数声明同样会前置,如果我们使用函数表达式那么规则和变量一样,如下图:
如果我们使用函数声明的方式,那么即使函数写在最后也可以在前面语句调用,前提是函数声明部分已经被下载到本地。
3、arguments 是什么
是一个长的很像数组的对象,可以通过该对象获取到函数的所有传入参数。
4、函数的重载怎样实现
在JavaScript中没有函数重载的概念,函数通过名字确定唯一性,参数不同也被认为是相同的函数,后面的覆盖前面的。函数调用没必要把所有参数都传入,只要你函数体内做好处理就行,但前提是传的参数永远被当做前几个。
5、立即执行函数表达式是什么?有什么作用
立即执行函数表达式有多种写法:(function(){})();
, 或(function(){}());
,或!function(){}();
,或void function(){}();
, 如下图所示:
作用:创建一个独立的作用域。这个作用域里面的变量,外面访问不到(即避免变量污染)。
比如下面这个例子:不管单击哪个li,alert出来的总是6,而不是0、1、2、3、4、5。因为我们一定是在for循环结束后才单击的,而i是贯穿整个作用域的,所以,i总是6.
<ul>
<li>li1</li>
<li>li2</li>
<li>li3</li>
<li>li4</li>
<li>li5</li>
<li>li6</li>
</ul>
<script type="text/javascript">
var liList=document.getElementsByTagName("li");
for(var i=0; i<liList.length; i++){
liList[i].onclick=function(){
alert(i);
}
}
</script>
这里我们就可以用立即执行函数给每个li创造一个独立的作用域来解决这个问题。
当然也有其他解决方法
6、什么是函数的作用域链
JavaScript中所有的量都是存在于某一个作用域中的,在试图访问一个变量时JS引擎会从当前作用域开始向上查找直到Global全局作用域停止。
如下图:当alert(A)时, JS引擎沿着D的作用域, B的作用域, 全局作用域的顺序进行查找,这三个作用域组成的有序集合就成为作用域链。
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('hunger', 28, '男');
getInfo('hunger', 28);
getInfo('男');
输出:
name:hunger;
age:28;
sex:男;
["hunger", 28, "男"]
name:valley;
name:hunger;
age:28;
sex:undefined;
["hunger", 28]
name:valley;
name:"男";
age:undefined;
sex:undefined;
["男"]
name:valley;
8.写一个函数,返回参数的平方和
function sumOfSquares(){
var sum=0;
for(var i=0; i<arguments.length; i++){
sum=sum+Math.pow(arguments[i],2);
}
console.log(sum);
}
sumOfSquares(3,5); //34
sumOfSquares(3,5,-2); //38
sumOfSquares(3,5,-2,"hello"); //NaN
9.如下代码的输出?为什么
console.log(a); //underfined,因为变量提升的缘故,初始值undefined
var a = 1;
console.log(b); //报错,因为b没有声明
10.如下代码的输出?为什么
sayName('world'); //输出hello world,因为使用函数声明声明的函数,相当于整个函数都被前置了,可以在声明之前就被调用
sayAge(10); //会报错,因为使用表达式声明的函数,只是函数名被前置了,所以在声明之前调用会报错
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
11.如下代码的输出?为什么
function fn(){}
var fn = 3;
console.log(fn); //3,因为当在同一个作用域内定义了名字相同的变量和方法的话,无论其顺序如何,变量的赋值会覆盖方法的赋值
12.如下代码的输出?为什么
function fn(fn2){
console.log(fn2);
var fn2 = 3;
console.log(fn2);
console.log(fn);
function fn2(){
console.log('fnnn2');
}
}
fn(10);
输出
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');
}
}
因为,**当函数执行有命名冲突的时候,函数执行时载入顺序是变量、函数、参数 **,所以原代码等同于如下代码:
function fn(fn2){
var fn2; //变量声明前置
function fn2(){ //函数声明前置
console.log('fnnn2');
}
console.log(fn2); //打印fn2()函数
fn2 = 3;
console.log(fn2); //打印数字3
console.log(fn); //向上寻找,打印fn()函数
}
fn(10);
13 .如下代码的输出?为什么
var fn = 1;
function fn(fn){
console.log(fn);
}
console.log(fn(fn));
执行报错。代码等同于:
var fn; //变量声明前置
function fn(fn){ //函数声明前置
console.log(fn);
}
fn=1; //fn赋值为1
console.log(fn(fn)); //报错,因为此时的fn是数字1
14.如下代码的输出?为什么
//作用域
console.log(j); //undefined,变量声明前置导致
console.log(i); //undefined,变量声明前置导致
for(var i=0; i<10; i++){
var j = 100;
}
console.log(i); //10,因为i=9时,j=100,然后再执行i++,i=10,此时不满足条件i<10,跳出循环。
console.log(j); //100,j一直等于100.
15.如下代码的输出?为什么
fn();
var i = 10;
var fn = 20;
console.log(i);
function fn(){
console.log(i);
var i = 99;
fn2();
console.log(i);
function fn2(){
i = 100;
}
}
会依次打印:undefined,100,10,分析如下;
var i, fn;
function fn(){
var i;
function fn2(){
i = 100;
}
console.log(i); //undefined,因为此时fn2()函数没有被调用,所以i没有被赋值,打印undefined
i = 99;
fn2(); //此处调用了fn2()函数,但是由于fn2()函数没有返回值,所以此处没有打印,但是i已经被赋值为100,并且是全局变量
console.log(i); //打印出i的值100
}
fn();
i=10; //此处i被重新赋值为10
fn=20;
console.log(i); //打印重新赋值后的i值
16.如下代码的输出?为什么
var say = 0;
(function say(n){
console.log(n);
if(n<3) return;
say(n-1);
}( 10 ));
console.log(say);
依次输出:10,9,8,7,6,5,4,3,2,0
括号内是一个立即执行函数,创建了一个独立的作用域,这个作用域里的变量,外面访问不到。第一次传入参数10,打印10,由于n=10不满足条件(n<3),于是执行函数say(n-1),打印9,接着是8,7......3,2,当n=2时,满足条件(n<3),于是跳出函数,执行console.log(say);
,打印0。
© 本文归饥人谷和本人所有,如需转载请注明来源。