函数声明和函数表达式有什么区别 (*)
在javascript中,函数有两种定义写法,函数定义表达式和函数声明,其例子分别如下所示:
var test = function(x){
return x;
}
function test(x){
return x;
}
尽管函数定义表达式和函数声明语句包含相同的函数名,并且都创建了新的函数对象,但是这二者却有区别。
-函数声明语句中的函数名是一个变量名,变量指向函数对象。
-函数定义表达式和通过var声明变量一样,其函数被提前到了脚本或函数的顶部,因此它在整个脚本和或函数内都是可见的。这样的话,只有函数变量声明提前了,函数的初始化代码仍然在原来的位置。但是使用函数声明的话,函数名称和函数体均提前了,即脚本中的函数和函数中嵌套的函数都会在当前上下文中其它代码之前声明,也即可以在声明一个函数之前调用它。
例如:
test(1);
function test(x){
console.log(x);
}
上面代码能正常执行。输出结果为1,这时候函数变量声明提前了。相当于
function test(x){
console.log(x);
}
test(1);
运行不会报错。
而对于
test(1);
var test = function(x){
console.log(x);
}
而这时,只相当于函数变量声明提前了,函数的初始代码仍然在原位。即:
var test;
test(1);
test = function(x){
console.log(x);
}
当运行到test(1);的时候就会报错.
什么是变量的声明前置?什么是函数的声明前置 (**)
-变量的声明前置:
-所谓的变量声明前置就是在一个作用域块中,所有的变量都被放在块的开始出声明
例如:
var a=10;
function v(){
console.log(c);
var c=100;
}
v();
这时候运行v() 控制台输出 undefined;就是因为变量的声明前置;上面代码和下面代码一致。
var a=10;
function v(){
var c;
console.log(c);
c=100;
}
v();
当运行到console.log(c)的时候变量c只是声明了。还未定义。则会显示undefied;
-函数的声明前置
-函数的声明前置和变量声明前置类型。只是函数表达式并不会发生声明前置。例如
console.log(typeof foo);
console.log(typeof bar);
console.log(typeof add);
//函数的声明
function foo(){
alert('foo');
}
//命名函数表达式
var bar = function(){
alert('bar');
};
// 函数表达式-匿名函数
var add = function(a,b){
return a+b;
};
arguments 是什么
-arguments 是JavaScript里的一个内置对象,有的函数都有属于自己的一个arguments对象
-函数的 arguments 对象并不是一个数组,但是访问单个参数的方式与访问数组元素的方式相同。
例如:
function main(){
for(var i=0;i<arguments.length;i++){
console.log(arguments[i]);
}
}
main("21a",21,"one")
这样就利用arguments对传输进来的数据进行遍历。
函数的重载
-JS中不存在函数的重载,而C++,java中函数的重载时利用相同名称的函数,参数个数和参数顺序的不同认为是不同的函数,称之为函数的重载。
-在JS中,函数依据函数名称确定唯一性,相同名称函数,后者会覆盖前者(即使参数个数和参数顺序不同.)
立即执行函数表达式是什么?有什么作用
立即执行函数表达式是 例如
(function sayHello() {
alert("hello");
}() );
或者:
(function sayHello() {
alert("hello");
}) ();
其主要作用是:
-隔离作用域,当函数执行完,其内部定义的变量就释放了,不会与外部变量发生冲突;相当于人为创建一个块级作用域,而JS本身没有块级作用域。
-封装一段代码而不会引起而不会遗留任何全局变量,定义的变量都是立即执行函数的局部变量;
什么是函数的作用域链?
当代码在执行时候,会创建变量对象的一个作用域链。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。js没有块级作用域,只有函数作用域。
例如:
var color="blue";
function getColor(){
var otherColor="red";
function changeColor(){
vae tempColor=otherColor;
otherColor=color;
color=tempColor;
//这里可以访问 tempColor otherColor 和color
}
changeColor();
// 这里可以访问 otherColor,color
}
//这里只能访问color
getColor();
代码
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, '男');
getInfo('hunger', 28);
getInfo('男');
输入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 sumOfSquares(){
var sum=null;
for(var i=0;i<arguments.length;i++){
sum+=(arguments[i]*arguments[i]);
}
console.log (sum);
}
sumOfSquares(2,3,4); // 29
sumOfSquares(1,3); // 10
3..如下代码的输出?为什么 (难度*)
console.log(a);
var a = 1;
console.log(b);
_________________________
console.log(a) //输出 1
console.log(b)//报错显示b undefied.
因为发生了函数声明前置,例子代码与下面代码相同:
var a;
console.log(a);
a=1;
console.log(b);
4.如下代码的输出?为什么?
sayName('world');
sayAge(10);
function sayName(name){
console.log('hello ', name);
}
var sayAge = function(age){
console.log(age);
};
___________
会输出 hello,world;
sayAge 报错,显示undefined
因为变量声明和函数声明会前置,但函数表达式不会前置:转换后如下例所示:
var sayage;
function sayName(name){
console.log('hello ', name);
}
sayName('world');
sayAge(10);
ayAge = function(age){
console.log(age);
};
5.如下代码的输出?为什么 (难度**)
function fn(){}
var fn = 3;
console.log(fn);
————————
输出3
var fn;
function fn(){};
fn=3;
console.log(fn);
相当于先声明一个变量fn,再创建一个函数fn,此时会覆盖之前声明的fn,然后 将3赋值给函数fn,最后输出3
6..如下代码的输出?为什么 (难度***)
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){
var fn2;
function fn2(){
console.log('fnnn2');
}
console.log(fn2);
fn2 = 3;
console.log(fn2);
console.log(fn);
}
可以将上例函数转换为:
function fn(fn2){
var fn2;
function fn2(){
console.log('fnnn2');
}
console.log(fn2);
fn2 = 3;
console.log(fn2);
console.log(fn);
}
当输入 fn(10)的时候。
遇到var fn2; 这时候 fn2等于10;
function fn2(){} 没有被调用 跳过。
console.log(fn2);输出函数fn2:
function fn2(){
console.log('fnn2')
}
然后将3赋值给fn2,
遇到console.log(fn2);输出3
然后遇到console.log(fn)输出 函数 fn();
7.如下代码的输出?为什么 (难度***)
var fn = 1;
function fn(fn){
console.log(fn);
}
console.log(fn(fn));
报错fn undefied
————————
var fu;
function fn(fn){
console.log(fn);
}
fu=1;
console.log(fn(fn));
我不知道这样解释对不对。
因为当函数和变量声明前置,函数的声明覆盖了变量的声明,最后1赋值给fu,这时候fu类型不是function而是number,这时候console.log(fn(fn)) 就报错。显示fn不是一个函数。
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
___________
此处没有 什么变量提升,所以开始console.log(j);和console.log(i)都会报错
然后经过一个for循环后 i=10 j=100。
而且不会随着循环的结束而消失,。然后console.log(i)和console.log(j) 就为10 和100
9.如下代码的输出?为什么 (难度****)
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);//undefined
i = 99;
fn2();
console.log(i);//100
}
fn();
i = 10;
fn = 20;
console.log(i);//10
前面直接跳过,到fn(),会执行函数fn() 先声明一个局部变量var.这里面开始并不会执行fn2(){} 到console.log(i)。
因为这里i只是声明了,并没有定义,所有会得到undefined ;然后将99赋值给局部变量i.然后执行fn2(),会得到一个变量I,由于没有用var声明,此处I 在fn()中有效,所有console.log(i)等于100。
然后将10赋值为变量i,20赋值给fn;
得到console.log(i) 为10.
10.如下代码的输出?为什么 (难度*****)
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
因为函数为自执行函数,变量只在函数作用域内生效,并不会影响到外面的变量。所以左后console.log(say)输出0
网友评论