任务17作业

问答:

函数声明和函数表达式有什么区别?

  • 函数声明必须带有标示符(即函数名称),而函数表达式则可以省略这个标示符。
function 函数名称 (参数:可选){ 函数体 } 
  函数表达式: 
  function 函数名称(可选)(参数:可选){ 函数体 } 
  • 可以看出,如果不声明函数名称,它肯定是表达式,可如果声明了函数名称的话,如何判断是函数声明还是函数表达式呢?ECMAScript是通过上下文来区分的,如果function foo(){}是作为赋值表达式的一部分的话,那它就是一个函数表达式,如果function foo(){}被包含在一个函数体内,或者位于程序的最顶部的话,那它就是一个函数声明。还有一种函数表达式不太常见,就是被括号括住的(function foo(){}),他是表达式的原因是因为括号 ()是一个分组操作符,它的内部只能包含表达式。

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

  • JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行,这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升。例如:
var a=1;

而在实际工作的时候JavaScript是这样读取代码的,如下:

  var a;先读取变量而不读取其赋值,也就是说在运行过程中第一时间知晓有这么个定义变量存在。
  a = 1;  当读取完变量之后才会读取其赋值。

综上这就是传说中的变量声明前置。

  • 和变量的声明会前置一样,函数声明同样会前置,如果我们使用函数表达式那么规则和变量一样.例如:
console.log(fn); //undefined javascript中运行代码是一行一行逐一执行的,因此在这里就变量中读取到 (var a;)这里一样,console.log中需要执行的语句存在但是并没有定义,因此才会出现undefined。

var fn = function(){}

如果我们使用函数声明的方式,那么即使函数写在最后也可以在前面语句调用,前提是函数声明部分已经被下载到本地,例如:

fn(); // "1"
         执行函数fn;
function fn(){
    console.log('1');
}

arguments 是什么?

在JavaScript中,arguments对象是比较特别的一个对象,实际上是当前函数的一个内置属性。同时arguments对象的长度是由实参个数而不是形参个数决定的。形参是函数内部重新开辟内存空间存储的变量,但是其与arguments对象内存空间并不重叠。对于arguments和值都存在的情况下,两者值是同步的,但是针对其中一个无值的情况下,对于此无值的情形值不会得以同步。再次利用函数的arguments属性可以实现函数的重载。

函数的重载怎样实现 ?

  • 在这里首先我们要明确函数重载的定义:重载是很多面向对象语言实现多态的手段之一,在静态语言中确定一个函数的手段是靠方法签名——函数名+参数列表,也就是说相同名字的函数参数个数不同或者顺序不同都被认为是不同的函数,称为函数重载。
  • 在JavaScript中没有函数重载的概念,函数通过名字确定唯一性,参数不同也被认为是相同的函数,后面的覆盖前面的,这是不是意味着JavaScript不能通过重载功能实现一个函数,参数不同功能不同呢?

在JavaScript中,函数调用没必要把所有参数都传入,只要你函数体内做好处理就行,但前提是传的参数永远被当做前几个,看个例子:

function printPeopleInfo(name, age, sex){
    if(name){
        console.log(name);如前面所说:函数调用没必要把所有参数都传入,只要你函数体内做好处理就行,这里用条件过滤,满足要求则会执行相应的指令。
    }

    if(age){
        console.log(age);
    }

    if(sex){
        console.log(sex);
    }
}


printPeopleInfo('Byron', 26);这里两个参数在执行的时候会对参数进行判定,到底属于name age sex中的那一个;满足其中的两个,那么另一个就不会执行。

printPeopleInfo('Byron', 26, 'male');

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

  • 先创建了一个匿名函数,然后不传入参数调用它,这就变成了立即执行函数。例如:
(function(){})();

其实他的实际结构就是:

(函数定义表达式)函数调用表达式

再看一个例子:

 function fn(){
 console.log(1);
 }  
 这里定义了一个函数fn,也就是说fn这个函数就是 前面function fn(){}; 这个整体,那么他的直接调用就是后边:(function fn(){
 console.log(1);
 })();当然这里我们没有加入实参。
 fn();调用此函数

什么是函数的作用域链?

在大多数语言中都是用花括号{}来形成一个作用域,但是在JavaScript中{}并没有带来块作用域,JavaScript的作用域是靠函数来形成的,也就是说一个函数内定义的变量函数外不可以访问,从而就形成了一个特有的作用区域,俗称作用域。看个例子:

function fn(){
  var a =1;

  if(a > 2){
    var b = 3;
  }
  console.log(b);
}

fn(); // undefined

console.log(a); // "ReferenceError: a is not defined  报错a没有被定义,个人觉得函数中并没有执行a,因此在函数外执行console.log(a)就没法执行,因为获取不到a的信息,也就是没有在函数的作用域中。

代码:

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这里重新定义name为valley
        console.log('name', name); 6
    }

    getInfo('hunger', 28, '男');
输出//name: hunger    1  js中的代码逐行执行,因此对应上边的函数依次解析参数。
           age: 28           2
           sex: 男            3
    ["hunger", 28, "男"] 4 arguments数组
      name valley         6
    getInfo('hunger', 28);
输出://name: hunger    1
             age: 28             2
            sex: undefined   3
              ["hunger", 28]  4 arguments数组
               name valley    6 

    getInfo('男');
输出:// name: 男           1
             age: undefined   2  无参数 所以undefined
             sex: undefined   3
               ["男"]               4
             name valley       6

2、写一个函数,返回参数的平方和?如 (难度**)

function sumOfSquares(){ }
 sumOfSquares(2,3,4); // 29
 sumOfSquares(1,3); // 10

答案如下:
  function sumOfSquares(){
     var sum =0; 定义一个变量
     for(var i=0;i<arguments.length;i++){
 sum += arguments[i]*arguments[i]
}利用函数的arguments属性实现重载
     console.log(sum); 打印出sum的值                            
}
sumOfSquares(1,3);   输出10
sumOfSquares(2,3,4); 输出29

3、如下代码的输出?为什么 ?

console.log(a);  输出undefined  变量前置
 var a = 1;
 console.log(b); 报错找不到b

4、如下代码的输出?为什么 ?

sayName('world'); // hello  world
sayAge(10);// 报错  sayAge不是一个函数
 function sayName(name){
 console.log('hello ', name); }
 var sayAge = function(age){ // 相当于是定义一个变量,因此并不是函数,所以不能执行。
console.log(age); 
};

5、如下代码的输出?为什么?

function fn(){} //这里fn是一个函数
var fn = 3; // 此处对fn进行了重新定义,覆盖了前者。
console.log(fn);因此此处应该显示3,但是浏览器中执行的时候是报错。报错内容为:标识符的fn已经宣布。

6、如下代码的输出?为什么?

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){
function fn2(){
            console.log('fnnn2');  
        }
      var fn2;
       console.log(fn2); 显示fnnn2
       fn2 = 3;//此处重新定义fn2,因此下边的执行会显示3
       console.log(fn2); //显示3
       console.log(fn);  //显示10
     }
    fn(10);

7、如下代码的输出?为什么 ?

var fn = 1; //定义fn为1
 function fn(fn){ console.log(fn); } //这是一个函数声明,无法自动执行
console.log(fn(fn));  //因此在这里会报错,报错原因是由于前边对变量fn进行了定义,而且权重高于函数,如果后边是console.log(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
作用域存在于函数中的时候才存在局部作用域,当没有函数的时候,除了特殊定义,其余皆可视为全局变量,因此在该题中 第一行和第二行代码的执行结果为undefined,这也正好体现在js中代码是逐行执行的,当执行到for循环的时候,便将i和j视为全局变量,根据条件对i的限制有0-9共计执行10次,因此console.log(i)为10,与此同时变量j被定义为100,因此执行console.log(j)为100.

9、如下代码的输出?为什么?

 fn(); // 这里是指执行函数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; } }
根据函数声明提前,上题中的代码可以写成:
 function fn(){
 console.log(i);
 var i = 99;
 fn2();
 console.log(i);
 function fn2(){ i = 100; }
代码逐行执行,后边覆盖前面,因此在这个局部作用域中i的最终值是100,所以该大函数fn的执行结果就是100
 }
 fn(); 显示100
 var i = 10; 全局变量重新定义i
 var fn = 20;
 console.log(i); 因此此处显示为10

故而输出结果为:100 10

10、如下代码的输出?为什么?

var say = 0;
 (function say(n){ 
console.log(n);打印出n
 if(n<3) 条件判断,当n小于3的时候返回结果,后边就不执行。
return; 
say(n-1);执行n-1 }( 10 ) );、
因此此处的执行结果为10 9 8 7 6 5 4 3 2 但是为什么没有1呢?
因为当n=3的时候 依次执行console.log(3) 显示3 同时后边执行say(3-1); 显示2 , 当n=2的时候 满足了后边的if条件,就执行return,所以没有1.
 console.log(say); 最后在执行这个 因为前面定义了变量say=0,所以此处显示0.

首先声明一点,上题中
(function say(n){ 
console.log(n);
 if(n<3) 
return; 
say(n-1); }( 10 ) );是一个立即执行函数相当于();只不过括号里边是一个函数声明而已,但是后边的10是实参,也就是N的初始值为10.

综上 执行结果为10 9 8 7 6 5 4 3 2 0

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

推荐阅读更多精彩内容