JS基础知识知多少(二)--函数

通常来说,一个函数就是一个可以被外部代码调用(或函数本身递归调用)的“子程序”。和程序本身一样,一个函数的函数体是由一系列的语句组成的。

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

syntax:
函数声明:
<pre> function函数名称(参数:可选){函数体}</pre>
函数表达式:
<pre>functuion函数名称(可选)(参数:可选){函数体}</pre>
如果声明了函数名称的话,当function 函数名称(){}是作为赋值表达式的一部分的话,那它就是函数表达式;如果function函数名称(){}被包含在一个函数体内,或者位于程序的最顶部的话,那它就是一个函数声明。
区别在于:
a.函数声明会在任何表达式被解析和求值之前先被解析和求值,即使声明在代码的最后一行,它也会在同作用域内第一个表达式之前被解析/求值。示例:
<pre>
alert(fn());
function fn() {return 'Hello world!';}
</pre>
b.函数声明在条件语句内虽然可以用,但是没有被标准化,也就是说不同的环境可能有不同的执行结果,所以这样情况下,最好使用函数表达式:
c.函数声明的syntax:
<pre>function 函数名(){}</pre>
函数表达式的syntax:
<pre>var 变量名=function 函数名(){};</pre>

函数声明结尾没有分号,但是函数表达式以分号结尾。

2.什么是变量的声明前置?什么是函数的声明前置?
变量的声明前置:JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果就是所有的变量的声明语句,都会被提升到代码的头部,也称为变量提升。
函数的声明前置:函数声明过程在整个程序执行之前的预处理就完成了,所以只要在同一作用域,就可以访问到,即使在定义之前调用也可以。

3.arguments 是什么 ?
arguments是一个类数组对象。代表传给一个function的参数列表。是函数内部的本地变量;arguments已经不再是函数的属性了。可以在函数内部通过使用arguments对象来获取函数的所有参数。这个对象为传递给函数的每个参数简历一个条目,条目的索引号从0开始。(MDN

4.函数的重载怎样实现?
JavaScript没有重载函数这个概念,但是可以通过arguments来模拟函数重载。实现代码示例:
<pre>
function sum(){
var sum=0;
for(var i=0;i < arguments.length;i++){
sum+=arguments[i];
}
return sum;
}
sum(1,2);
</pre>

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

立即执行函数表达式是函数定义完直接调用。
syntax:
<pre>a.(function(){/code/}());</pre>
<pre>b.(function(){/code/})();</pre>
<pre>c.!function(){/code/}();</pre>

作用:
a.js没有块级作用域,用来隔离作用域避免污染,或者截断作用域链,避免闭包造成引用常量无法释放;
b.利用立即执行特性,返回需要的业务函数或对象,避免每次通过条件判断来处理。

6.什么是函数的作用域链 ?
javascript中,变量的作用域有全局作用域和局部作用域两种。
a.全局作用域:在代码任何地方都能访问到的对象拥有全局作用域
b.局部作用域:一般只在固定的代码片段内可以访问到。
c.函数作用域链:在JavaScript中,函数也是对象,实际上,JavaScript里一切都是对象。函数对象和其它对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性。其中一个内部属性是[[Scope]],由ECMA-262标准第三版定义,该内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问。

代码题:
1.以下代码输出什么?
<pre>
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('男');
</pre>
输出结果:
<pre>
getInfo('hunger', 28, '男');
name:hunger
age:28
sex:男
["hunger",28,"男"]
name valley
</pre>
<pre>
getInfo('hunger', 28);
name:hunger
age:28
sex:undefined
["hunger",28]
name valley
</pre>
<pre>
getInfo('男');
name:男
age:unfined
sex:unfined
["男"]
name valley
</pre>

2.写一个函数,返回参数的平方和?
<pre>
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
</pre>

3.如下代码的输出?为什么 ?
<pre>
console.log(a); // undefined,变量提升
var a = 1;
console.log(b);//报错,b is not defined
</pre>

4.如下代码的输出?为什么 ?
<pre>
sayName('world'); //函数sayName声明提前
sayAge(10); //函数sayAge声明
function sayName(name){
console.log('hello ', name); //输出:hello world
}
var sayAge = function(age){ //函数表达式
console.log(age); //报错,sayAge is not a function.函数表达式的声明不能提前
};
</pre>

5.如下代码输出?为什么?
<pre>
function fn(){}
var fn = 3;
console.log(fn);
</pre>

可以写成:
<pre>
var fn;
function fn(){}
fn=3;
console.log(fn);
</pre>
输出结果为:3,var fn变量提升,function fn(){}函数声明前置,第三行代码给fn赋值3,使其作为变量输出。

6.如下代码输出?为什么
<pre>
function fn(fn2){
console.log(fn2);
var fn2 = 3;
console.log(fn2);
console.log(fn);
function fn2(){
console.log('fnnn2');
}
}
fn(10);
</pre>
<pre>
解析:
a.fn(10)调用函数function fn(fn2){}将10赋值给fn2;
b.由于函数声明前置,console.log(fn2)输出
function fn2(){
console.log('fnnn2');
}
c.var fn2=3给fn2重新赋值,console.log(fn2)输出3;
d.console.log(fn)输出:
function fn(fn2){
console.log(fn2);
var fn2=3;
console.log(fn2);
console.log(fn);
function fn2(){
console.log('fnnn2');
}
}
</pre>
7.如下代码的输出?为什么?
<pre>
var fn = 1;
function fn(fn){
console.log(fn);
}
console.log(fn(fn));
</pre>
输出结果:
<pre>
代码相当于:
var fn;
function fn(fn){
console.log(fn);
}
fn=1;
console.log(fn(fn));
报错:fn is not a function
原因是:变量声明提前和函数声明前置,但是function fn(fn){}的声明在前面,之后给变量赋值,变量赋值会覆盖函数的声明,因此会报错。
</pre>
8.如下代码的输出?为什么?
<pre>
//作用域
console.log(j);
console.log(i);
for(var i=0; i<10; i++){
var j = 100;
}
console.log(i);
console.log(j);
</pre>
输出结果:
<pre>
console.log(i);//undefined,变量提升,因为没有赋值,所以输出是undefined
console.log(j);//undefined,变量提升,因为没有赋值,所以输出是undefined
for(var i=0;i<10;i++){
var j=100;
}//定义全局变量i和j
console.log(i);//10
console.log(j);//100
结果为:
undefined
undefined
10
100
</pre>

9.如下代码的输出?为什么 ?
<pre>
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;
}
}
</pre>
输出结果:
<pre>
a.调用函数fn(){};
b.运行函数fn(){};
function fn(){
var i;
console.log(i);//变量提升,变量声明但没有赋值,输出undefined
i = 99;
fn2(); //调用函数fn2(),函数声明前置
console.log(i);//输出100
function fn2(){
i = 100;
}
}
c.var i=10;给i赋值10,覆盖之前的100,console.log(i)输出10
所以结果为:
undefined
100
10
</pre>
10.如下代码的输出?为什么 ?
<pre>
var say = 0;
(function say(n){
console.log(n);
if(n<3) return;
say(n-1);
}( 10 ));
console.log(say);
</pre>
输出结果:
<pre>
(function say(n){
console.log(n);
if(n<3) return;
say(n-1);
}( 10 ));为立即执行表达式;
输出结果为:
10
9
8
7
6
5
4
3
2
最后的console.log(say)输出全局变量say:0
</pre>

参考文章:
1.汤姆大叔的博客
2.Back to Basics: JavaScript Hoisting
3.为什么要有js立即执行函数,存在的意义是什么?
4.JavaScript作用域链

版权归本人所有,若有转载,请注明来源

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

推荐阅读更多精彩内容

  • 1. 函数声明和函数表达式有什么区别 (*) 函数在JS中有三种方式来定义:函数声明(function decla...
    进击的阿群阅读 440评论 0 1
  • 继承 一、混入式继承 二、原型继承 利用原型中的成员可以被和其相关的对象共享这一特性,可以实现继承,这种实现继承的...
    magic_pill阅读 1,054评论 0 3
  • 函数声明和函数表达式有什么区别 (*)解析器会率先读取函数声明,并使其在执行任何代码之前可以访问;函数表达式则必须...
    coolheadedY阅读 385评论 0 1
  • 1. 有一天清早刚起床,电话铃声响起,拿起电话,电话那头说话,有气无力,说一句停一下,听了一会儿才知道,X姐...
    如果一切都可以阅读 342评论 0 2
  • 开启了尘封很久的上班模式,穿着标准正装,脚穿皮鞋,彰显一身专业,重新回到了打工的地方,又开启被公司“圈养”的时刻。...
    感受背影阅读 181评论 0 0