JavaScript基础--函数声明,函数的作用域链
函数声明和函数表达式区别
函数声明是通过 function 函数名(){}来声明一个函数
函数表达式是通过声明一个变量,然后赋值函数。
两者区别是,在程序执行前,会先获取函数声明声明的函数,获取变量的声明,这里变量的声明只是先开辟一个空间,然后给了个名字,之后到该变量名赋值的时候,才有值,也就是说,在未得到该变量的赋值前,使用该变量会得到undefined。
而无论你把函数放在放在程序中的开头或者结尾,函数的执行语句都能正常执行。
fn();//输出 fn
console.log(fn2);// undefined 声明了,没有值,自动赋值undefined
function fn(){console.log('fn')}//函数声明
var fn2 = function(){console.log('fn2')};//函数表达式
fn2();//输出 fn2
变量的声明前置和函数的声明前置
变量的声明前置,在程序运行前,先获取变量的名字,到该变量的赋值语句,才为该变量赋值,再此前都是undefined。
函数的声明前置:function 函数名(){}声明了一个函数,在程序运行前,提取所有函数声明的函数,之后才正式开始运行函数,所以,无论函数声明的函数执行语句放在程序的最前面,或者程序的最后面,都能够正常执行。
例子:
fn();//输出1
function fn(){console.log(1)}
fn();//输出1
console.log(a);//undefined
var a = 2;
console.log(a);//输出2
arguments 是什么?
arguments是函数内部的一个对象,对应着传进来的参数,是一个类数组对象,没有数组的操作方法。
每个传进来的参数对应着arguments[0],arguments[1],有先后顺序之分。
比如function fn(name,age){
console.log(arguments[0];);
console.log(arguments[1];);
}
javascript中函数的重载?
在javascript中没有函数重载,因为相同的函数名字,如果定义的参数个数不一样,后出现的会覆盖先出现的。
所以,通过内部访问arguments可以不用管传进来多少个参数,尽管访问就可以了,但是传进来的参数有先后之分。
什么是立即执行函数表达式,作用是什么?
1.(function(){})()
2.(function(){}())
作用:
1.函数会立即执行。
2.这个匿名函数中的变量与外部环境的变量隔离,防止了变量的命名冲突,形成了一个独立的空间,有助于代码模块化。
函数的作用域链是什么?
函数的作用域链:JavaScript没有块级作用域,只有使用函数来实现块级作用域,在全局环境下,是访问不到函数内部的变量,而函数可以访问外部的变量,而当函数内部有这个变量的时候,就不会去函数的作用域外去寻找。
当函数内部以及外部作用域都没有该变量的时候,会报undefined。总而言之,在函数内部有指定的要访问的变量的时候,不会往作用域外部去寻找,如果没有的话,就需要从函数的作用域外部去寻找,而外部的函数无法访问内部函数的变量,就是所谓的函数作用域链。
代码示例:
1.下面的代码输出什么
function getInfo(name, age, sex){
console.log('name:',name);//1
console.log('age:', age);//2
console.log('sex:', sex);//3
console.log(arguments);//4
arguments[0] = 'valley';//5
console.log('name', name);//6
}
getInfo('hunger', 28, '男');
//输出:1.name:hunger, 2.age: 28, 3 sex:男, 4['hunger',28,'男'], 5 下标0赋值为valley,6valley
getInfo('hunger', 28); getInfo('男');
//输出:1.name:hunger ,2 age:28, 3.sex:undefined 4.['hunger',28],5赋值,6valley
* 2.写一个函数,返回参数的平方和?如 (难度**)
function sumOfSquares(){
var sum = 0;
if(arguments.length>0){
for(var i=0;i<arguments.length;i++){
sum += arguments[i]*arguments[i];
}
}
return sum;
}
3.如下代码的输出?为什么 (难度*)
sayName('world');//打印 hello world
sayAge(10);//报错,sayAge不是一个函数,未赋值
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
4.如下代码的输出?为什么 (难度***)
function fn(fn2){
console.log(fn2);//输出函数fn2
var fn2 = 3;//赋值3
console.log(fn2);//输出3
console.log(fn);//输出函数fn
function fn2(){
console.log('fnnn2');
}
}
fn(10);//返回undefined
5.如下代码的输出?为什么 (难度***)
var fn = 1;
function fn(fn){
console.log(fn);
}
console.log(fn(fn)); //输出fn不是一个函数,因为函数声明提前,之后又被赋值覆盖了,所以fn不是一个函数
6.如下代码的输出?为什么 (难度****)
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;
}
}
1.先执行函数fn
2.内部有i,但是赋值语句在后面,所以输出undefined
3.执行fn2,因为里面的函数没有i,所以执行完后,就把原先的i=99又赋值为100,
4.输出100
5.执行完函数fn了,把全局变量i赋值为10,fn赋值为20,
6.输出10
10.如下代码的输出?为什么 (难度*****)
var say = 0;//变量声明
(function say(n){
console.log(n);
if(n<3) return;
say(n-1);
}( 10 ));//立即执行函数,有自己独立的空间,所以不会覆盖外部的say变量
console.log(say);
1.(function say(){console.log(n)})(10)先打印n,之后判断,如果小于3就返回
2.在未返回前,都打印一次n,之后递归调用自己,n-1,直到小于3。
3.依次打印:
立即执行函数:10,9,8,7,6,5,4,3,2
console.log(say):0