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); 

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 09:04:23

js 变量、函数提升的相关文章

javascript 变量/函数 提升

1.JavaScript hoisting(变量/函数 提升) 以下实验都是通过firefox的Console做的实验. console.log(a); ReferenceError: a is not defined console.log(a); 但是,如果在后面加上变量的定义的话,结果将会变得不同. console.log(a); var a = 10; undefined 之前变量没有定义的错误没了,取而代之的是告诉我们a的值是 'undefined'. 先不管a的值缘何为 'undef

js中函数提升及var变量提示

其中,在javascript中,函数声明及var声明的变量会得到提升.但是函数声明会先于var声明的变量被提升.即便function写在后面. 看下面的例子: var aa = 221; function aa(){ alert(111); } console.log(aa); //221 说明了函数声明先被提升了.而后面的var aa声明覆盖了aa函数,所以打印出来的是 ------ 221. 上面的语句在浏览器解析的时候其实是这样的. function aa(){ alert(111); }

js变量声明提升

1.变量提升 根据javascript的运行机制和javascript没有块级作用域这个特点,可以得出,变量会声明提升移至作用域 scope (全局域或者当前函数作用域) 顶部的. 变量声明提升至全局域 console.log(a); // undefined var a ="Hi"; 相当于 var a; // 变量提升到全局作用域 console.log(a); // 已声明变量a,但未初始化,固为undefined a="Hi"; 变量声明提升至当前函数域 v

js 变量声明易混淆的几点知识

这是我 JavaScript 学习过程中遇到的一些容易混淆的地方,趁着有时间,做了一个整理. 变量提升 变量与函数名提升优先级 js 作用域内有变量,这个很好理解,但有一些细节需要注意. console.log(foo); // 函数 function foo(){ console.log("函数声明"); } console.log(foo); // 函数 var foo = "变量"; console.log(foo); // 变量 当变量名与函数名同名,且都提

js中变量名提升和函数名提升

首先,js中变量没有块级作用域,但是有函数作用域,即只有函数可以约数变量的作用域. 并且,函数的实质也是一个变量,所以可以改变它的值,即赋值.所以变量名提升和函数名提升非常相像. 1.变量名的提升发生在函数内部.看下面的例子.说明:第一个因为弹出undefined,相当于在上面定义了var num;因为函数内部,定义了var num=20:就相当于在一开始定义了var num;这就是变量名的提升. var num = 10; function func() { alert(num); //und

js 函数和变量的提升

1. 函数的作用域: js中 ,函数的作用域为函数,而不是大括号. var hei = 123;if(true){ hei = 456;}console.log(hei);// 456; var hei = 123;if(true){ (function(){ var hei = 456;})(); }console.log(hei); // 123 函数内部可以用用函数外部的变量,而函数外部的不可以用函数内部的变量(可以用闭包实现效果,随后总结). (function(){ var hei =

深入理解js的变量提升和函数提升

一.变量提升 在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域.变量提升即将变量声明提升到它所在作用域的最开始的部分.上个简历的例子如: 1 2 3 4 5 6 7 8 9 10 console.log(global); // undefined var global = 'global'; console.log(global); // global function fn () { console.log(a); // unde

js变量提升与函数提升

在es6之前,js语言并没有块级作用域,即{}形成的作用域,只有全局作用域和函数作用域,所谓的提升,即是将该变量的声明或者函数的声明提升,举个例子 console.log(global); //undefined var global = 111; console.log(global);//111 显然,上面代码处于一个全局的作用域中,在该作用域中使用var声明了一个global变量,其实际的声明过程如下: var global; console.log(global); //undefine

js中的变量提升与函数提升

先看看一个简单的代码 var str='Hello World'; alert(str);//弹出 Hello World 再看一段代码: var v='Hello World'; (function(){ alert(v); })() //和我们预期的一样,还是弹出 Hello World 那么铺垫完了,继续coding var str='Hello World'; (function(){ alert(str); var str='I love coding...'; })() //出乎我们