JavaScript 函数
1.函数声明和函数表达式有什么区别?
函数声明:function FunName(){}
函数表达式:var FunName = function (){}
区别:函数声明中函数名是必须的;函数表达式中则是可选的。用函数声明定义的函数,函数可以在函数声明之前调用,而用函数表达式定义的函数只能在声明之后调用。因为解析器对这两种定义方式读取的顺序不同:解析器会先读取函数声明,即函数声明放在任意位置都可以被调用;对于函数表达式,解析器只有在读到函数表达式所在那行的时候才执行。
2.什么是变量的声明前置?什么是函数的声明前置?
console.log(a);//undefined,因为变量声明提升了
var a = 1;
console.log(b);//报错,因为变量b还没声明
变量的声明前置:JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部.
fn(); //1
function fn(){
console.log('1');
}
也就相当于
function fn(){
console.log('1');
}
fn(); //1
函数的声明前置:在使用函数声明的函数定义方法的时候,函数调用可以放在任意位置,也就是说函数声明提前的时候,函数声明和函数体均提前了。
3.arguments 是什么?
是JavaScript里的一个内置对象。使用 arguments 对象来获取函数的所有参数:
用过arguments来改变参数的值:
arguments非常类似Array,但实际上又不是一个Array实例。
4.函数的重载怎样实现?
重载是很多面向对象语言实现多态的手段之一,在静态语言中确定一个函数的手段是靠方法签名——函数名+参数列表,也就是说相同名字的函数参数个数不同或者顺序不同都被认为是不同的函数
通过使用arguments来实现函数的重载
function sum(){
var sum = 0;
for(var i=0; i<arguments.length; i++){
sum = sum + arguments[i];
}
return sum;
}
console.log( sum(1,2));
5.立即执行函数表达式是什么?有什么作用?
立即执行函数表达式:Immediately-Invoked Function Expression,简称IIFE。
//正确的语法
(function(){
/* code */
}());
//或
(function(){
/* code */
})();
var fnName=function(){
alert('Hello World');
}();
//函数表达式后面加括号,当javascript引擎解析到此处时能立即调用函数
function fnName(){
alert('Hello World');
}();
//不会报错,但是javascript引擎只解析函数声明,忽略后面的括号,函数声明不会被调用
function(){
console.log('Hello World');
}();
//语法错误,虽然匿名函数属于函数表达式,但是未进行赋值操作,
//所以javascript引擎将开头的function关键字当做函数声明,报错:要求需要一个函数名
在function前面加!、+、 -甚至是逗号等到都可以起到函数定义后立即执行的效果,而()、!、+、-、=等运算符,都将函数声明转换成函数表达式,消除了javascript引擎识别函数表达式和函数声明的歧义,告诉javascript引擎这是一个函数表达式,不是函数声明,可以在后面加括号,并立即执行函数的代码。
作用:
(1)可以单独形成一个局部变量,这样就可以防止全局被污染;
(2)立即执行函数表达式内部定义的变量不会和外部的变量发生冲突;
(3)模拟块作用域、解决闭包冲突、模拟单例。
6.什么是函数的作用域链?
函数作用域:作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。
当js需要查找变量x的值的时候(这个过程称为变量解析(variable resolution)),它会从链的第一个对象开始查找,如果这个对象有一个名为x的属性,则会直接使用这个属性的值,如果第一个对象中没有名为x的属性,js会继续查找链上的下一个对象。如果第二个对象依然没有名为x的属性,则会继续查找下一个,以此类推。如果作用域链上没有任何一个对象含有属性x,那么就认为这段代码的作用域链上不存在x,并最终抛出一个引用错误(ReferenceError)异常。
var name = "one";
function test(){
var name = "two";
function test1(){
var = "three";
console.log(name);//three
}
function test2(){
console.log(name);//two
}
test1();
test2();
}
test();
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('男');
8.写一个函数,返回参数的平方和?如
function sumOfSquares(){
for(var i = 0, arr = 0; i < arguments.length; i++){
arr = arr+ arguments[i]*arguments[i];
}
console.log(arr);
}
sumOfSquares(2,3,4); //29
sumOfSquares(1,3);//10
9.如下代码的输出?为什么
console.log(a);//undefined,因为变量提升,先执行var a,再执行console.log(a),最后执行a = 1
var a = 1;
console.log(b);//报错,因为没有声明b变量
10.如下代码的输出?为什么
sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);//hello world,因为函数的声明前置
}
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 fn(fn2){
var fn2;
function fn2(){ //函数声明覆盖变量的声明,所以fn2变为函数
console.log('fnnn2');
}
console.log(fn2);//打印上面的fn2
var fn2 = 3;
console.log(fn2); //3,因为上面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;//变量声明覆盖了函数声明
console.log(fn(fn));
14.如下代码的输出?为什么
console.log(j);
console.log(i);
for(var i=0; i<10; i++){
var j = 100;
}
console.log(i);
console.log(j);
因为for循环语句不是函数,变量也就不会前置,所以里面的变量也就是全局变量。
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;
}
}
上面代码等同于:
var i;
var fn;
function fn(){
var i
function fn2(){
i = 100;
}
console.log(i);//因为变量i只在自己作用域里面找,而i只被声明了,没有赋值,所以是undefined
i = 99;
fn2();
console.log(i); //在上一步中执行了fn2,并且还赋值了100,所以打印出来的是100
}
fn();
i = 10;
fn = 20;
console.log(i);//打印出10
16.如下代码的输出?为什么
var say = 0;
(function say(n){
console.log(n);
if(n<3) return;
say(n-1);
}( 10 ));//10,9,8,7,6,5,4,3,2,此函数为立即执行函数,而且传递了参数10,从10依次递减到2时,满足条件2<3,所以立即跳出该循环,输出10到2
console.log(say);//在这个作用域下,say已经赋值了且为0,所以打印出来就是0