问答:
1.函数声明和函数表达式有什么区别
函数声明 函数声明由 function +函数名+([参数])+{函数体} 组成
console.log(typeof fn); //这里输出不是undefined 而是 function 由于 函数声明提前的作用
fn(); //函数调用
function fn(){ //函数声明
console.log("hello")
}
javaScript引擎将函数名视同变量名,所以采用 function声明函数时,整个函数(也就是说包括函数体里面的代码)会像变量声明一样,被提升到代码头部。所以上面的代码不会报错。
函数表达式
fn(); //报错 Uncaught ReferenceError: fn is not defined
var fn=function(){
console.log("hello")
}
fn(); //hello
}
函数表达式只有个执行到var fn=function(){}之后才能够调用。
所以在如下代码中,虽然函数声明在函数表达式的后面,但是由于函数声明被声明提前了,所以是函数表达式相当于在函数的后面,函数表达式覆盖了函数声明部分。
var fn=function(){
console.log("world");
}
function fn(){
console.log("hello");
}
fn(); //最后的结果是world.
2.什么是变量的声明前置?什么是函数的声明前置
变量的声明前置是指变量名的声明前置
console.log(fn); //这里并没有提示 fn is not defined 而是提示undefined
//说明变量fn已经声明过了但是没有赋值
var fn=0;
相当于
var fn;
console.log(fn);
fn=0;
函数的生命前置是指整个函数(包括函数体)的声明前置
console.log(fn); //输出 function fn(){console.log("hello")}
function fn(){
console.log("hello")
}
所以在如下代码中
console.log(fn); //输出 function fn(){}
var fn=1;
function fn(){};
console.log(fn); //由于被覆盖 fn的值变为1;
上面的代码相当于
var fn; function fn(){};
console.log(fn);
fn=1;
console.log(fn);
3.arguments 是什么
arguments是函数的参数集合,在函数内部,你可以使用arguments对象获取到该函数的所有传入参数。
function fn(){
console.log(arguments);
}
fn(2,3) //[2, 3]
4.函数的重载怎样实现
在java中重载(overloading) 是在一个类里面,方法名字相同,而参数不同
参数不同:包括 对应位置的参数的类型不同,参数的数量不同。
而作为javascript这种弱类型语言 我们只需要实现 参数的数量不同就可以了
我们可以使用arguments来实现方法的重载;
function fn(){
var sum=0;
for(var i in arguments){
sum+=arguments[i];
}
return sum;
}
fn(2,3);
fn(1,2,3);
5.立即执行函数表达式是什么?有什么作用
立即执行表达式就是在函数定义后立即执行;
而JavaScript引擎规定,如果function关键字出现在行首,一律解释成语句。所以我们一般用括号括上,变成函数表达式+括号 来立即调用
立即执行函数表达式= 函数表达式+([参数]);
常用的写法
(function fn1(){console.log("hello")})();
(function fn2(){console.log("world")}());
//其中函数名可以省略
(function (){console.log("hello")})();
它的目的有两个:
一是不必为函数命名,避免了污染全局变量;
即使是命名了函数名 也会在执行后销毁
(function fn1(){console.log("hello")})();
console.log(fn1); //报错 Uncaught ReferenceError: fn1 is not defined
二是IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量
6.什么是函数的作用域链
我们首先要理解什么是作用域
作用域包括 全局作用域和局部作用域
- 全局作用域(Global Scope)
全局作用域有两种定义方式
- 定义在最外层的的变量拥有全局作用域
- 末定义直接赋值的变量自动声明为拥有全局作用域(这种情况应该避免)
function fn(){
global="hello";
var inner= "world";
}
fn();
console.log(global);//未定义变量自动声明为拥有全局作用域
console.log(inner) //报错 inner is not defined
2.局部作用域(Local Scope)
和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部,
函数内部可以访问到,在外部不可以。
function fn(){
var inner= "world";
console.log(inner);
}
fn();
console.log(inner) //报错 inner is not defined
函数会首先从函数内部开始查找局部变量,然后逐级向上查找,直到全局变量,这样便形成了一个关于作用域的链条。
var a=1;
function fn1 (){
var b=10;
function fn2(){
console.log(a);
console.log(b);
}
fn2();
}
fn1();
参考文档:
阮一峰的Blog
梦想天空的Blog
饥人谷的课件
代码
1.以下代码输出什么? (难度**)
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, '男'); // 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
2.写一个函数,返回参数的平方和?如 (难度**)
function fn(){
var sum=0;
if(arguments.length==0) return 0;
for(var i in arguments){
var temp=+arguments[i];
if(temp!==temp) continue;
sum+= temp*temp;
}
return sum;
}
3.如下代码的输出?为什么 (难度*)
console.log(a); //undefined 变量声明提前
var a = 1;
console.log(b); //报错 b is not defined
4.如下代码的输出?为什么 (难度*)
sayName('world'); //hello world
sayAge(10); //报错 sayAge is not a function
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
5.如下代码的输出?为什么 (难度**)
function fn(){}
var fn = 3;
console.log(fn); //3 由于fn被覆盖
6.如下代码的输出?为什么 (难度***)
function fn(fn2){
console.log(fn2); //输出fn2 函数 实参被函数覆盖掉了
var fn2 = 3;
console.log(fn2); //输出3
console.log(fn); //输出fn 函数
function fn2(){
console.log('fnnn2');
}
}
fn(10);
7.如下代码的输出?为什么 (难度***)
var fn = 1;
function fn(fn){
console.log(fn);
}
console.log(fn(fn)); //fn是1 不是函数
8.如下代码的输出?为什么 (难度**)
//作用域
console.log(j); //undefined
console.log(i); ////undefined
for(var i=0; i<10; i++){
var j = 100;
}
console.log(i); //10
console.log(j); //100
9.如下代码的输出?为什么 (难度****)
fn();
var i = 10;
var fn = 20;
console.log(i); //10 fn函数没有改变全局变量 i的值
function fn(){
console.log(i); //undefined 没有执行到 var i=10 i 未定义
var i = 99;
fn2();
console.log(i); //100 由于fn2 中未定义i fn2 改变的是 fn中 i的值
function fn2(){
i = 100;
}
}
10.如下代码的输出?为什么 (难度*****)
var say = 0;
(function say(n){
console.log(n);
if(n<3) return; //递归调用 直到n=2 后结束 10,9,8,7,6,5,4,3,2,
say(n-1);
}( 10 ));
console.log(say); //立即执行函数执行完后销毁 ,不会影响say 0