JS函数

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

函数声明:
function func(){
    console.log(1)
}
函数表达式:(一般匿名函数赋给一个变量)
var tmp = function (){
    console.log(1)
};
因此函数声明和函数表达式不同之处在于:
    1、js引擎在解析javascript代码时会[函数声明提升],把当前执行环境(作用域)上的函数声明给提到执行环境的前头;而函数表达式则必须是等到js引擎执行到它所在的那行代码,才会从上而下一行一行地解析函数表达式中的代码
    2、函数声明之后,只需要 func()即可调用;而函数表达式后面可以加括号作为立即执行函数调用,函数声明则不可以。
    3、函数声明是以function关键词开始,如果不是,那么它就是函数表达式。
    4、函数声明最后面一般不写分号,而函数表达式有分号。

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

js引擎的工作方式:先解析代码,获取所有被声明的变量,然后一行一行执行,会把所有的变量的声明语句都被提到代码的头部,这就叫做变量的声明前置。

  • 变量的声明前置:
    ①变量前置就是把变量的声明提前到当前作用域的最前面,但变量的赋值仍然按照原来的顺序执行,如果变量声明但未被赋值,变量会自动赋值为undefined。
var a = 2;
等同于
var a;
a = 2;
  • 函数的声明前置:
    ①函数声明前置和变量的声明前置实质是一样的。函数的声明前置有两种情况,一个是使用函数声明,则整个声明都前置,而且会被前置到变量声明的后面;另一个是使用函数表达式,那么规则和变量的声明前置一样。
fn()
function fn(){
    console.log(1)
}//1
等同于
function fn(){ console.log (1) }
fn()
  • 函数表达式的声明前置:
fn(1)
var f = function fn(n){
    console.log(n)
}
等同于
var f;
fn(1)
f = function fn(n){
    console.log(n)
}
//Uncaught ReferenceError: fn is not defined(…)

疑问:写上面这题的函数表达式用具名函数还是匿名函数规范呢?


3.arguments 是什么

  • 在函数内部,可以使用arguments对象获取到该函数传入的全部参数,一般简称为[参数列表]
    (1).arguments是一个类数组对象,代表传给一个function的参数列表,只在函数内部起作用。arguments的值与函数传入实参有关,与函数定义形参无关。
    (2).即使函数声明时不用详细写清楚传入的参数的个数和名称,也能使用arguments获取参数。
    (3).arguments是一个伪数组,无真正数组的API(eg:push、pop那些方法)。
    (4).arguments.length:指的是实参的长度,不是形参的长度
    (5).arguments是function的隐含属性,它将会把实参显示成一个类组对象。
function fn(a,b,c){
    console.log(arguments)
    console.log(arguments.length)
}
fn(1,2,3,4)
11.png

4.函数的重载怎样实现

①重载是很多面向对象语言实现多态的手段之一,相同名字的函数参数个数不同或者顺序不同都被认为是不同的函数,称为函数重载。
②在JavaScript中没有函数重载的概念,函数通过名字确定唯一性,参数不同也被认为是相同的函数,后面的覆盖前面的

那是否意味着JS不能通过重载功能来实现一个函数,参数不同功能不同呢?
答:JavaScript可以通过自身的属性去模拟函数重载;可以用arguments来实现函数的重载(关键只要传实参的个数有所不同即可)

22.png

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

立即执行函数表达式(Immediately-Invoked Function Expression)简称IIFE
通俗点解释:平时写语句是无需得出结果,但是表达式是需要求出结果的。所以推测出立即执行函数表达式字面意思是一个为了马上得出结果的函数。

  • 立即执行函数表达式是什么?
    (1).声明一个匿名函数
    (2).马上调用这个匿名函数
    (3).声明一个匿名函数function(){} ,然后在匿名函数后面加一对括号() ,调用这个匿名函数
    (4).在function前面加!、 +、 — 、()可以起到函数定义后立即执行的效果,加上运算符后,就告诉js引擎这是一个函数表达式,不是函数定义。
典型一:(function(){  alert("我是匿名函数")    })()
典型二:(function(){  alert("我是匿名函数")    }())
典型三:!function (){  alert("我是匿名函数")  }()
典型四:var fn =function(n){console.log(n)}(1) //1
  • 立即执行函数表达式有什么作用?
    作用:创建一个独立的作用域;这个作用域里面的变量,外面访问不到(即避免[变量污染]);
    当同时调用多个JS的情况时,很容易造成因为变量名一致或函数名一致而覆盖其他库的变量;所以才需要采用立即执行函数;
    定义的变量都成了立即执行函数的局部变量,以后即使变量名或函数名一样也不被污染,同时形成了一个单独的作用域,可以封装一些外部无法读取的私有变量;

6.什么是函数的作用域链

①作用域:作用域就是变量与函数的可访问范围,作用域控制着变量与函数的可见性和生命周期

  • 全局变量:变量没有在函数内声明或者声明的时候没有带var就是全局变量,拥有全局作用域;
  • 局部变量:函数内部声明并且以var修饰的变量就是局部变量,只能在函数体内使用,函数的参数虽然没有使用var但仍然是局部变量。

②注意:JavaScript并没有块级作用域,只有函数作用域:变量在声明它们的函数体及其子函数内是可见的。

③作用域链:
作用域链用来变量查询的,在代码执行查找过程中,变量会在当前作用域中进行寻找,如果找不到,就会往沿着作用域链向上一级进行寻找,一直到全局作用域为止,如果找到便会停止(而不理会上一级是否有同名的变量),如果找不到,就会报错。

④作用域只会逐层向上查找,遵循就近原则,只要查找到就停止了。


33.png

代码:

1.以下代码输出什么?

44.png

2.写一个函数,返回参数的平方和?

//题目:写一个函数,返回参数的平方和
// function sumOfSquares(){
// }
// sumOfSquares(2,3,4);   // 29
// sumOfSquares(1,3);   // 10

--------
方法1:
function sumOfSquares(){
  var result = 0
  for(var i=0; i<arguments.length; i++){
    result += arguments[i]*arguments[i]
  }
  return result
}
console.log( sumOfSquares(2,3,4) );   // 29
console.log( sumOfSquares(1,3) );   // 10
-----------
方法2:
function sumOfSquares(){
  var result = 0
  for(var i=0; i<arguments.length; i++){
    result += arguments[i]*arguments[i]
  }
  console.log(result)
}
sumOfSquares(2,3,4);   // 29
sumOfSquares(1,3);   // 10

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

 console.log(a);//打印为undefined,定义了但未赋值
 var a = 1;
 console.log(b);//b is not defined,b没有声明,所以直接报错

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

sayName('world'); 
sayAge(10); 
function sayName(name){ 
    console.log('hello ', name);
 }
 var sayAge = function(age){ 
    console.log(age); 
};
等同于
var sayAge  
function sayName(name){   //定义时不看函数体内容
    console.log('hello ', name);
 }
sayName('world')      // 输出:hello world
sayAge(10)      //输出:sayAge is a not function ;相当于undefined(10),肯定会报错
sayAge = function(age){ 
    console.log(age); 
};

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

function fn(){}
var fn = 3; 
console.log(fn);
等同于
var fn;          //变量的声明前置
function fn(){}//声明提升,函数声明在变量的后面,函数覆盖变量
fn = 3;       //变量的赋值覆盖函数的声明
console,log(fn)  //输出3

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

function fn(fn2){ 
   console.log(fn2);   //函数fn2
   var fn2 = 3; 
   console.log(fn2);   //3
   console.log(fn);    //外层fn函数
   function fn2(){ 
        console.log('fnnn2');  
     } 
  } 
fn(10);

等同于
function fn(fn2){
    var fn2;
    //注意:传参数时隐式做了 var fn2 = 10
    function fn2(){console.log('fnnn2')};  //函数声明前置覆盖了之前的变量
    console.log(fn2);// 输出上面的fn2(){}函数
    fn2 = 3;
    console.log(fn2); //3
    console.log(fn); //输出最外层的fn函数,当前作用域(函数fn内部)中没有这个变量,因此向上一级寻找,找到变量fn被声明为函数
}
fn(10)

分析:
1.当输入 fn(10)的时候,把fn2 直接赋值成了数值10;
2.刚进入函数体内部时,var fn2; 这时候 fn2还是等于10;
3.接着被赋值成数值的fn2,又被声明回函数;
4.这个时候console.log(fn2);,那就输出函数fn2;
5.然后又被赋值成数值3;
6.遇到console.log(fn2);输出3
7.然后遇到console.log(fn),输出函数 fn();

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

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

等同于
var fn;
function fn(fn){
    console.log(fn)
}
fn = 1;
console.log(fn(fn)); //居然是报错!is not a function 

第七题解析:因为当函数和变量声明前置,函数的声明覆盖了变量的声明,最后1赋值给fn,这时候fu类型不是function而是number,这时候console.log(fn(fn)) 转换就变成console.log(1(1)) ,所以console.log(fn(fn)) 就报错。显示fn不是一个函数。
ps:请老师解析下,这题好悬,我是在控制台打出才得知会报错


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
-------
等同于
var i;
var j;
console.log(j);
console.log(i);
i=0;
for(i<10;i++){//只有函数才有作用域,for循环没有作用域,所以里面的变量是全局变量
    j = 100
}
console.log(i)
console.log(j)
for循环后i跳出就变成10;循环10次后j被赋值了依然还是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 fn2函数运行后,本来全局的i=99被fn2的i=100覆盖了
}
fn();  //然后执行函数fn
i = 10; //全局 i 给再次赋值10
fn =20;
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);
------
等同于
var say;
(function say(n){ //立即执行函数
    console.log(n); //输出:10 9 8 7 6 5 4 3 2
    if(n<3) return;
    say(n-1); 
}( 10 ));
say = 0
console.log(say);//输出:0
//变量只在函数作用域内生效,并不会影响到外面的变量。所以最后console.log(say)输出0

分析:
1.声明var say = 0; 
2.立即执行函数表达式不会提升的,按位置立即执行;
3.进入函数,实参10赋给形参n,n = 10,首先打出console.log(10) ;
4.判断语句if n<3 return,不满足条件,执行say(n-1);继续输出n,一直递归下去 ;
5.直到n=2的时候,n<3此时返回,结束循环,return为空值的时候,就是return出undefined,函数执行完毕;
6.console.log(say)输出0 ,因为立即执行函数表达式就是创建一个独立的作用域;这个作用域里面的变量,外面是访问不到,所以打出全局定义的变量say;

本文版权归区子铭和饥人谷所有,转载请注明来源。

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

推荐阅读更多精彩内容

  • 函数声明和函数表达式有什么区别 (*)解析器会率先读取函数声明,并使其在执行任何代码之前可以访问;函数表达式则必须...
    coolheadedY阅读 385评论 0 1
  • 1. 函数声明和函数表达式有什么区别 (*) 函数在JS中有三种方式来定义:函数声明(function decla...
    进击的阿群阅读 440评论 0 1
  • 概念 1、函数声明和函数表达式有什么区别? ECMAScript规定了三种声明函数方式: 构造函数首先函数也是对象...
    周花花啊阅读 465评论 1 1
  • 函数声明和函数表达式有什么区别? 函数声明和函数表达式是EMACScript规定的两种不同的声明函数的方法。1.函...
    LeeoZz阅读 346评论 0 1
  • 一、问答1、函数声明和函数表达式有什么区别 ()函数声明和函数表达式都是声明函数的方法。函数声明:function...
    崔敏嫣阅读 347评论 0 0