1.函数声明的方式

JavaScript声明函数有两种选择:函数声明法,表达式定义法。

  • 函数声明法
function sum (num1 ,num2){   
      return num1+num2  
  }
  • 表达式定义法
var sum = function(num1,num2){   
      return num1+num2  
  };

2.扒一扒两种函数声明的区别

解析器会率先读取函数声明(也就是说函数声明的优先级较高),并使其在执行任何代码之前可以访问(将函数声明提升到代码树顶部);至于函数表达式声明,则必须等到解析器执行到它所在的代码行,才会执行,无法自动提升。

同样的函数使用不同的定义方式,调用的时候会产生不同的效果。

// 函数声明法
var num = add(1, 2);
console.log(num);// 3

function add(a, b) {
    return a + b
}

// 函数表达式声明
var num = add(1, 2);
console.log(num);//Uncaught TypeError: undefined is not a function 

var add = function (a, b) {
    return a + b
}

我们来看一看这两种声明方式到底对代码产生了怎样的影响。

首先看函数声明,由于发生了代码提升,实际的代码如下

// 函数声明法
function add(a, b) {
    return a + b
}
var num = add(1, 2);
console.log(num);// 3

//function add(a, b) {
//    return a + b
//}

再看表达式声明法,同样将变量add提升,add()函数调用的时候,只声明了变量add,却没有进行赋值。(此时的add变量是undefined)实际的代码如下。

// 函数表达式声明
var add;
var num = add(1, 2);
console.log(num);//Uncaught TypeError: undefined is not a function 

add = function (a, b) {
    return a + b
}

3.关于变量提升和执行顺序

JavaScript是解释型语言,但它并不是逐行执行的。解析过程可以理解为两个阶段:一个是预处理阶段,JavaScript将脚本代码转换为字节码,该过程中将所有定义的变量提升到代码树顶端;第二个阶段,JavaScript解释器借助执行环境,把字节码生成机械码,该过程中才发生变量的赋值,并顺序执行。

console.log(a); 
//Error:a is not defined ,直接报错,下面语句没法执行,以下结果为注释该句后结果  
console.log(b) //undefined  ,变量发生提升
var b="Test";  
console.log(b);//Test

也就说JavaScript值执行第一句语句之前就已经将函数/变量声明预处理了

var b="Test" 相当于两个语句

var b;(undefined结果的来源,在执行第一句语句之前已经解析)

b=”Test”(这句是顺序执行的,在第二句之后执行)

这也是为什么我们可以在方法声明语句之前就调用方法的原因。

4.练一练

下面我们用一个经典的面试题目的一部分来对本篇文章进行总结

请问下面这段代码的执行结果是什么?

function Foo() {      
    getName = function () {   
        alert (1);   
    };      
    return this;  
}  

Foo.getName = function () {   
    alert (2);  
};  

Foo.prototype.getName = function () {   
    alert (3);  
};  

var getName = function () {   
    alert (4);  
};  

function getName() {   
    alert (5);  
}  


getName()

答案加载中...

答案加载中...

答案加载中...

答案加载中...

答案加载中...

答案加载中...

答案加载中...

答案加载中...

答案加载中...

答案加载中...

答案加载中...

答案加载中...

答案加载中...

答案加载中...

揭晓答案:

4

这里我主要讲解一下第二问中为什么是4,其他的在后续文章中进行说明。上面的代码实际上是这个样子滴

function Foo() {      
    getName = function () {   
        alert (1);   
    };      
    return this;  
}  
var getName;//只提升变量声明  
function getName() { //提升函数声明,覆盖var的声明  
    alert (5);  
}  
Foo.getName = function () {   
    alert (2);  
};  
Foo.prototype.getName = function () {   
    alert (3);  
};  
getName = function () { //最终的赋值再次覆盖function getName声明  
    alert (4);  
};  
getName();//最终输出4