Js中的预解析机制与定义函数的三种方式
Js中,定义函数的方式有三种:
- 函数声明(也是用的最多的,推荐优先使用)
//函数声明的语法
function fn (){
console.log("这是函数声明的方式");
}
fn();//直接调用函数名
- 函数表达式(也叫匿名函数)
var fn = function([参数列表]){
console.log("这是一个匿名函数");
}
/*
顾名思义,因为这种写法是把函数赋给了一个变量,函数并没有真正的名字
因此就叫匿名函数
*/
fn();//调用匿名函数,使用变量名称加();
- 自执行函数
//顾名思义
//,自己执行自己,并且在声明的同时就调用自己,只能调用一次
//有两种写法,先写第一种:
(function(){
console.log("这是一个自执行函数");
})();
为什么要这样子写呢,我大概介绍一下:
他是由函数表达式演变过来的
var fn = function(){}
fn();
把fn替换成:
function(){},
就成了:
function(){}();
为了保持整体性,在function加上一个(),所以就变成了
(function([这里是形参]){})([这里是实参])
//第二种写法:
(function(){
console.log("这是一个自执行函数");
}())
值得注意的是,用这种写法会有一个小漏洞
再来举个栗子吧
var fn = function(){
console.log(123);
}
(function(){
console.log(789);
}())
最后输出如下图
/*
匿名函数fn明明没调用啊,怎么也会输出呢,下面我把代码简化一下,你们就能看懂了!
*/
var fn = function(){
console.log(123);
}(function(){console.log(789);}())
/*
可以很明显的看到(function(){console.log(789);}())这个自执行函数调用输出了789,同时,这个自执行函数跟在匿名函数的后面,Js解析的时候把这个匿名函数也解析成为了自执行函数,所以就输出了123.
解决的办法很简单,在第一个匿名函数的后面加一个;或者直接采取第一种写法就能避免这种问题
*/
Js预解析机制
预解析过程:
1.把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值。
2.把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用。
3.先提升var,在提升function
因此我们在定义函数的时候,绝大多数都使用第一种方式(函数声明的方式)
匿名函数多用 定时器里面和注册事件的时候,比如
btn.onclick = function(){
console.log("这是一个匿名函数");
}
下面给大家举个栗子,理解一下预解析机制
var num = 123;
function fn(){
console.log(num);
var num = 123;
}
fn();//调用fn函数
/*
此时控制台打印的是undefined,解释一下
Js解析代码时,把函数的声明还有变量的声明提升到当前作用域的最前面,所以代码就变成:
*/
//var num;
//num = 123;
//function fn(){
// var num; //从这里可以看出num只是声明而没有定义赋值
// console.log(num); //输出的时候必然是undefined
// num = 123;
//}
//fn();