JavaScript关于函数

问答

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

函数声明形式:

function sayHello(){
  console.log("Hello, World! ");
}

函数表达式形式:

var sayHello = function(){
  console.log("Hello, World! ");
};

在声明一个变量的时候,javascript解释器会将变量声明的语句提前,函数声明形式会发生函数声明前置,所以代码如果放在使用之后也可以生效,而函数表达式形式只发生了变量声明前置,如果在定义之前使用,函数名目前还只是一个变量名,不能用()进行执行,会抛出错误。

什么是变量的声明前置?什么是函数的声明前置 (**)

var a = 1;
//实际上相当于:
var a; //这句声明会提前到所有语句之前执行
a=1;

所以,

console.log(b); 
var b = 1;//console.log 并不会报错,而是返回变量声明之后的值undefined。

arguments 是什么 (*)

arguments 是一个可以接收所有函数传递参数的类似数组,在函数里可以直接取用。当函数的参数不确定数量的时候可以使用arguments对形参进行数组的方式操作,可以实现类似重载。

函数的重载怎样实现 (**)

function fn(){ 
  var sum = 0; 
  for(x in arguments ){
    sum=arguments[x]+sum;
  };
  console.log(sum);
}
//无论多少参数都可实现累加运算

立即执行函数表达式是什么?有什么作用 (***)

(function() {
  c =1 ;
  console.log(c)
})();

立即执行函数可以将写在函数体内的语句直接执行。区别于普通语句,立即执行函数内的变量不会干扰函数体外,形成一个类似区块的空间。

什么是函数的作用域链 (****)

函数对象其中一个内部属性是[[Scope]],由ECMA-262标准第三版定义,该内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问。
在函数执行过程中,每遇到一个变量,都会经历一次标识符解析过程以决定从哪里获取和存储数据。该过程从作用域链头部,也就是从活动对象开始搜索,查找同名的标识符,如果找到了就使用这个标识符对应的变量,如果没找到继续搜索作用域链中的下一个对象,如果搜索完所有对象都未找到,则认为该标识符未定义。函数执行过程中,每个标识符都要经历这样的搜索过程。


--JavaScript 开发进阶:理解 JavaScript 作用域和作用域链]

简单来说,函数作用域链用于查找函数内部变量的位置。在执行过程中,按照作用域链表的顺序依次进行查找。在函数每执行一次,这个表进行动态创建。所以,在实际使用中应当尽量减少全局变量的使用,避免with语句使用,如果一个跨作用域的对象被引用了一次以上,则先把它存储到局部变量里再使用。


代码

  1. 以下代码输出什么? (难度**)

  • 可以看出arguments 是参数的数组,可以对其进行修改,改变参数。
  • 当参数缺省的时候,定义为 undefined。
  • 参数是具有顺序的,第一个参数传递为第一个形参。
  1. 写一个函数,返回参数的平方和?如 (难度**)

function sumOfSquares(){
  var sum = 0;
  for(var x in arguments){
    sum += arguments[x]*arguments[x];
  }
  console.log(sum);
}

sumOfSquares(2,3,4);   // 29
sumOfSquares(1,3);   // 10
  1. 如下代码的输出?为什么 (难度*)

console.log(a);//返回 undefined
var a = 1;
console.log(b);//报错 提示未定义

因为声明前置,实际上在这段代码执行前就已经执行了var a;,所以在console.log(a)的时候不发生错误,返回undefined。

4.如下代码的输出?为什么 (难度*)

  • 由于函数声明前置,sayName可以正常执行
  • sayAge用了函数表达式形式,在赋值之前都不可以使用。

5.如下代码的输出?为什么 (难度**)

function fn(){}
var fn = 3;
console.log(fn);//3

结果比较直观,实际上将上面的语句颠倒也会输出相同的结果:

var fn = 3;
function fn(){}
console.log(fn);//3
  • 还是因为声明前置的原因,可以将声明都放到开头,再来理解:
var fn;
function fn(){}

fn = 3;
console.log(fn);//3

这就是上面那段代码实际执行的样子,这也就不难理解了。
需要注意的是,声明前置,变量的声明要比函数的声明要更早执行。

  function fn(){}
  var fn;  
  console.log(fn);

//function fn(){}

6.如下代码的输出?为什么 (难度***)

  • 在函数内部定义的函数,也会发生声明前置。上图中即使传入了参数10,但与函数内部函数重名,被覆盖掉了。此时console.log(fn2),打印出的就是fn2函数本身。此后fn2被重新赋值2,打印出3。

7.如下代码的输出?为什么 (难度***)

var fn = 1;
function fn(fn){
   console.log(fn);
}
console.log(fn(fn)); 

//Uncaught TypeError: fn is not a function(…)

实际执行过程,由于声明前置:

var fn;
function fn(fn){
   console.log(fn);
}

fn = 1;
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
  • 需要注意的是,for是属于运算符,不属于函数,所以在其内部定义的变量和当前属于同一个作用域。在JS中只有函数内部使用var定义,才具备另一个作用域性质。

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(); 
//undefined
//100
i = 10;
fn = 20;
console.log(i);//10

10.如下代码的输出?为什么 (难度*****)

  • 立即执行函数的内部定义的函数名、变量不会影响到函数外面。所以在其内部执行的say(),并没有覆盖函数外的say = 0; 在最后打印出来还是0 。
  • 函数内部有一个嵌套结构。使用嵌套时,函数名可以在function后定义。不需要的时候可以不加。
  • return的执行,伴随函数的退出,不再继续往下执行。

本教程版权归属于 张宇 及 饥人谷 所有,转载请说明来源~

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

推荐阅读更多精彩内容

  • 今天是函数基础部分!有点心理准备!老规矩,先放思维导图!图片哪里不懂,结合下面文字对应理解! 认识函数 在一个完整...
    范小饭_阅读 370评论 1 9
  • 一、函数声明和函数表达式有什么区别?(*) ECMAScript里面规定了三种声明函数的方式: 构造函数函数也是对...
    婷楼沐熙阅读 452评论 0 2
  • 问答: 1. 函数声明和函数表达式有什么区别 (*) 在日常的任务中,JavaScript主要使用下面两种方式创建...
    小木子2016阅读 313评论 0 0
  • 朋友一生一起走 那些日子不再有 一句话 一辈子 一生情 一杯酒 朋友不曾孤单过 一声朋友你会懂 还有伤 还有痛 还...
    21不思量阅读 200评论 0 0
  • Workflow真的是iOS上的一款效率神器,可以简化很多步骤,同时可以创造出很多有趣的功能。我也根据自己的需求,...
    Icebay阅读 1,033评论 0 0