level-17

函数声明和函数表达式有什么区别 (*)

在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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • 问答: 1. 函数声明和函数表达式有什么区别 (*) 在日常的任务中,JavaScript主要使用下面两种方式创建...
    小木子2016阅读 311评论 0 0
  • 一、函数声明和函数表达式有什么区别?(*) ** 1.ECMAScript里面规定了三种声明函数的方式**①构造函...
    鸿鹄飞天阅读 447评论 0 0
  • 1. 函数声明和函数表达式有什么区别 (*) 函数在JS中有三种方式来定义:函数声明(function decla...
    进击的阿群阅读 434评论 0 1
  • 继承 一、混入式继承 二、原型继承 利用原型中的成员可以被和其相关的对象共享这一特性,可以实现继承,这种实现继承的...
    magic_pill阅读 1,047评论 0 3
  • 作为天蝎座,我一般很少与人主动接触,无论是和谐的生活还是看不顺眼的撕逼,请原谅我把撕逼也称作交流 。 四年的大学宿...
    藜木莜瑾阅读 1,368评论 0 0