js 变量、函数提升

js 变量、函数提升

先简单理解下作用域的概念,方便对变量与函数提升的概念的理解

function foo() {
    var x = 1;
    if (x) {
        var x = 2;
    }
    console.log(x);
}
foo();// 2
结果为2,可见js中并没有块级作用域的概念
可以使用下面的方法创造自己的作用域,这样不会干扰到外部变量

function foo() {
    var x = 1;
    if (x) {
        (function() {
            var x = 2;
        }());
    }
    console.log(x);
}
foo();// 1
结果为1,可见js中的作用域是以函数为边界的

1.变量提升:

变量提升与js的预编译有关,下面通过例子辅助说明

var a = 100;
var b = 200;
function foo(){
    console.log(a);// undefined
    a = 10;
    console.log(a);// 10
    var a = 1;
    console.log(a);// 1
    console.log(b);// 200
}   
foo();
js预编译时会先在当前作用域中找到var声明的变量分配空间,赋值为undefined,如果找不到就会到下一级作用域中找

上面的代码的等价代码如下:

var a = 100;
var b = 200;
function foo(){
    var a;
    console.log(a);// undefined
    a = 10;
    console.log(a);// 10
    a = 1;
    console.log(a);// 1
    console.log(b);// 200
}   
foo();
这样看是不是容易理解多了。第一行var声明了a,但是没有赋值,因此为undefined,下面打印10、1也就顺理成章了。

至于变量b,它在当前作用域中找不到,因此需要到外层作用域中找,在window下找到了变量b,可以看到它的值为200


2.函数提升

首先要明确两点:

<1> 只有函数声明才会进行函数提升

<2> 函数提升会将函数体一起提升上去,这点与变量提升有所不同

下面来证明函数表达式不能进行函数提升:

~function() {
    alert(typeof next); // undefined
    ~function next() {
        alert(typeof next); // function
    }()
}()
函数前面加个~的目的是将函数声明变成函数表达式,实际上也可以加其它运算符,比如+,-,!等,总之这个函数声明被变成了函数表达式。

从打印结果来看第一个alert出的是undefined,说明next根本没有发生函数提升。

下面来接着验证:

a();// 123

var a = function(){
    console.log("321");
}

a();// 321

function a(){
    console.log("123");
}
从结果可以看出,先打印出来的反而是放在后面的a(),上面代码的等价表示如下:

var a = function a(){
    console.log("123");
}

a();

a = function(){
    console.log("321");
}

a();


那么如果当变量提升与函数提升同时发生的时候,哪个的优先级更高呢?我们来做个实验:

function fn(){
	console.log(a);
	var a = 2;
	function a(){}
	console.log(a);
}
fn();// function a(), 2
从打印顺序中可以看出,函数提升比变量提升优先级高,因为函数提升是将函数体整体提升,提升上去后立马赋值。等价代码如下:

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

下面再来几个有趣的例子:

B = 100;
function B(){
    B = 2;
    console.log(B);
}
B(); // B is not a function
//函数提升导致的


B = 100;
var B = function(){
    B = 2;
    console.log(B);
}
B(); // 2
//函数表达式不存在函数提升
function change() {
    alert(typeof fn); // function
    alert(typeof foo); // undefined
    function fn() {
        alert('fn');
    }
    var foo = function(){
    <span style="white-space:pre">	</span>alert('foo');
    }
    var fn;
}
change();
//fn提升了,foo没有提升

下面还有几个思考题:

1.

var a = 1;  
function b() {
    console.log(a);
    a = 10;  
    function a() {}  
}  
b();// ?
console.log(a);// ?
2.

a = 10;
(function a(){
    a = 1;
    console.log(a);// ?
})();
3.

function a(i) { 
    console.log(i);// ?
    var i = 1; 
    console.log(i);// ?
}; 
a(10); 


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值