函数

一、问答

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

Js中的函数声明是指下面的形式:

function functionName() {
  alert("Hello");
}

函数表达式则是类似表达式那样来声明一个函数,如:

var functionName = function() {
  alert("Hello");
}
functionName();

js的解析器对函数声明与函数表达式并不是一视同仁地对待的。
对于函数声明,js解析器会优先读取,确保在所有代码执行之前声明已经被解析;
而函数表达式,如同定义其它基本类型的变量一样,只在执行到某一句时也会对其进行解析。
所以在实际中,它们还是会有差异的,具体表现在,当使用函数声明的形式来定义函数时,可将调用语句写在函数声明之前,而后者,这样做的话会报错。

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

变量声明前置:javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,只要变量在代码中进行了声明,无论它在哪个位置上进行声明, js引擎都会将它的声明放在范围作用域的顶部。

console.log(a); //这个时候的输出结果为undefined,因为声明被前置了所以不会报错
var a = 1;

/*等同于:*/

var a;
console.log(a);
a = 1;

函数声明前置:和变量声明前置一样,因hoisting机制,执行代码之前会先读取函数声明,只要函数在代码中进行了声明,无论它在哪个位置上进行声明, js引擎都会将它的声明放在范围作用域的顶部。意味着可以把函数申明放在调用它的语句后面,但是函数表达式不行。

sayHi(); //此处输出结果“hi”,因为函数生命被前置了所以能正常调用
sayName(); //报错。仅仅是表达式里的变量sayName被前置了,此时未解析到函数
function sayHi() {
  console.log("hi");
}

var sayName = function() {
  console.log("Amy");
}

arguments 是什么?

arguments 是是JavaScript里的一个内置对象,所有的函数都有属于自己的一个arguments对象,它包括了函所有调用的参数,条目索引从 0 开始。他不是一个数组,如果用typeof arguments,返回的是'object'。

function myArray() {
  console.log(arguments[2]); //输出30
}
myArray(10,20,30);
函数的重载怎样实现?

JS函数没有重载这个概念,相同函数重复声明时,后面覆盖前面的。
但每一个函数都有一个特殊的参数arguments,可以通过它传递参数个数来实现不同效果。

<script type="text/javascript">
function add() {
    if (arguments.length == 1) {
        alert(arguments[0] + 10);
    }
    else if (arguments.length == 2) {
        alert(arguments[0] + arguments[1]);
    }
}
//函数调用
add(10);
add(10, 20);
</script>
立即执行函数表达式是什么?有什么作用?
//方法一:
(function myFunction() {
}()
)

//方法二:
(function myFunction() {
}
)()

用立即执行函数处理模块化可以减少全局变量造成的空间污染,构造更多的私有变量。

什么是函数的作用域链?

任何程序设计语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。

全局作用域:在代码中任何地方都能访问到的对象拥有全局作用域。

  • 最外层函数和在最外层函数外面定义的变量拥有全局作用域;
  • 所有末定义直接赋值的变量自动声明为拥有全局作用域;
  • 所有window对象的属性拥有全局作用域,例如:window.name、window.location、window.top等等。

局部作用域:和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部,所以在一些地方也会看到有人把这种作用域称为函数作用域。

当代码在一个环境中执行时,会创建变量对象的的一个作用域链(scope chain)。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是一个函数,则将其活动对象作为变量对象。
每一个函数都有自己的执行环境,当执行流进一个函数时,函数环境就会被推入一个环境栈中,而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境,这个栈也就是作用域链

参考

二、代码

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('男');

输出:

name: hunger
age: 28
sex: 男
["hunger", 28, "男"]
name valley

name: hunger
age: 28
sex: undefined
["hunger", 28]
name valley

name: 男
age: undefined
sex: undefined
[男]
name valley

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

function sumOfSquares(){ 
  var sum=0;
  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); //undefined  因为变量声明“var a”被前置
var a = 1; 
console.log(b); //报错  因为“b”未被声明

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

sayName('world'); //hello world 因为函数声明会被前置,所以调用语句写在函数声明之前也是可以正常调用的
sayAge(10); //报错 因为函数表达式不会被前置,此处未解析到函数
function sayName(name){ 
    console.log('hello ', name); 
} 
var sayAge = function(age){ 
    console.log(age); 
};

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

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

//等同于:

var fn;
function fn(){} 
fn = 3;
console.log(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){
    var fn2; //变量提升
    function fn2(){ 
        console.log('fnnn2'); 
    } //函数声明前置
    console.log(fn2); //打印函数fn2
    fn2 = 3;
    console.log(fn2); //3
    console.log(fn); //打印整个fn函数。在内部作用域内没找到fn,所以往父级找,找到fn这个函数
}
fn(10);



//结果:
function fn2(){ 
        console.log('fnnn2'); 
    }
3
fn(fn2){ 
    console.log(fn2); 
    var fn2 = 3; 
    console.log(fn2); 
    console.log(fn); 
    function fn2(){ 
        console.log('fnnn2'); 
    } 
}

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

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

//等同于:
var fn; //变量声明前置
function fn(fn){ 
    console.log(fn); 
};
fn = 1; //给fn值为1
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 循环结束时i的值为10
console.log(j); //100 j被赋值为100

//注:只有函数才具有作用域,上面代码的for循环里的变量属于全局变量会被提升到顶部。

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还没被赋值
    i = 99; 
    fn2(); 
    console.log(i); //100 i被赋值为100
}
i = 10; //i赋值为10
fn = 20;
console.log(i); //10

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

var say = 0; 
(function say(n){ 
    console.log(n);
    if(n<3) return; 
    say(n-1); 
}( 10 )); //n初始为10,立即执行函数输出10,9,8,7,6,5,4,3,2,小于3停止循环
console.log(say); //0 因为立即执行函数创造了私有作用域,外部不能访问内部变量,所以此处say为0

本教程版权归作者和饥人谷所有,转载须说明来源!

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

推荐阅读更多精彩内容

  • 1. 函数声明和函数表达式有什么区别 (*) 函数在JS中有三种方式来定义:函数声明(function decla...
    进击的阿群阅读 395评论 0 1
  • 函数声明和函数表达式有什么区别 (*)解析器会率先读取函数声明,并使其在执行任何代码之前可以访问;函数表达式则必须...
    coolheadedY阅读 368评论 0 1
  • 问答部分 一、函数声明和函数表达式有什么区别? 二者表示函数的方式不一样,如下 函数声明(函数名称不可少) 函数表...
    dengpan阅读 397评论 0 0
  • 问答: 1. 函数声明和函数表达式有什么区别 (*) 在日常的任务中,JavaScript主要使用下面两种方式创建...
    小木子2016阅读 297评论 0 0
  • 概念 1、函数声明和函数表达式有什么区别? ECMAScript规定了三种声明函数方式: 构造函数首先函数也是对象...
    周花花啊阅读 420评论 1 1