zoukankan      html  css  js  c++  java
  • 浅谈JavaScript变量声明提升

    前段时间阿里实习生内推,一面就被刷了,也是郁闷。今天系统给发通知,大致意思就是内推环节不足以了解彼此,还可以参加笔试,于是赶紧再投一次。官网流程显示笔试时间3月31日,时间快到了,开始刷题。网上搜了一下去年题目,我擦,第一题就不会(伤心中...),继续往下看,第四题也不会。。。好嘛,搜答案吧。搜了一个多小时的博客,结合自己的理解,写下了这篇博文。。。

    2014年阿里巴巴前端工程师笔试题目1:

    var v = "Hello world";
    	(function() {
    		console.log(v);
    		var v = "I love you";
    		bar();
    		foo();
    		 function bar(){
    		 	console.log("this is bar!");
    		 }
    		 
    		 var foo = function() {
    		 	console.log("this is foo!");
    		 };
    		 
    	})();
    请写出上面的运行结果并说出背后的理由。
    题目4:指出一下代码的运行结果,并解释为什么。
    function bar() {
    	return foo;
    	foo = 10;
    	function foo() {}
    	var foo = 11;
    }
    
    alert(typeof bar());

    其实上面两道题考察的核心是一样的,即JavaScript变量声明的相关概念,之前了解过一点,但了解的不是太深。

    要谈JavaScript变量声明,就离开不了作用域的问题。而JavaScript中没有类似C,JAVA等语言中的块级作用域。如:

    #include <studio.h>
    int main() {
    	int i = 1;
    	printf("d%",i); //1
    	if(1){
    		int i = 2;
    		printf("d%",i); //2
    	}
    	printf("d%",i); //1
    	return 0;
    }
    而JavaScript中相应的输出结果就变成了1,2,2。原因就是JavaScript中只有函数作用域,这也是导致JavaScript中一个经典问题的原因,即循环遍历DOM节点绑定事件后触发问题。如:

    window.onload = function() {
    	var oLi = document.getElementsByTagName("li");
    	for(var i=0,len=oLi.length;i<len;i++){
    		oLi[i].onclick = function() {
    			alert(i);
    		};
    	}
    };
    扯得有点远,下面还是说一下JavaScript语言中的变量声明提升的问题吧。

    1、当访问函数内的变量时,JavaScript会按照下面顺序查找:

    (1)语言级别:默认在所用作用域下的this,arguments

    (2)传入参数:函数命名的参数,作用域是当前函数体。

    (3)函数声明:如题1中的function bar() {} 与 题4中的function foo() {}

    (4)变量声明:如var v  与 var foo
    2、变量声明与函数声明经常被JavaScript引擎隐式的提升到当前作用域的顶部。

    2.1、变量声明:

    局部作用域内声明变量需要加关键词var,即

    function a(){
    	console.log(typeof b);
    	var b = 3;
    }
    实际上被解释成

    function a(){
    	var b;
    	console.log(typeof b);
    	b = 3;
    }

    而如果不加关键词var,则默认引用全局作用域内的相关变量,浏览器中即window作用域。如图:


    所以如果你能理解下面代码的运行结果是a=10,则说明对变量声明部分已经足够了解。

    <span style="white-space:pre">	</span>var a = 1;
    	function b() {
    		if(!a) {
    			var a = 10;
    		}
    		alert(a);
    	}
    	b();
    2.2、函数声明:我们都知道函数命名有两种方式,一种是函数声明方式function bar() {} 另外一种就是通过赋值语句的方式,即函数声明表达式var foo = function() {};

    而这两种函数命名方式虽然都会出现变量声明提升的现象,但第一种提升现象会包含函数体部分一起被提升,即整个函数bar被提升。而第二种则只是简单的变量提升(想象一下将赋值语句后面的函数代码改为基本变量,如数字5,则和上一步所说的变量声明部分完全吻合)。

    因此得出如下结论:

    (1)JavaScript中声明语句会被提升,而赋值语句不会被提升。

    (2)函数声明提升优先于变量声明提升。
    现在你应该能明白阿里笔试题1中输出结果是undefined this is bar! error:undefined is not a function. 题4中的结果是function.

    特此感谢以下博主的精彩博文:

    harmony的专栏《2014年阿里巴巴前端工程师笔试题》

    浪迹天涯《JavaScript中变量提升------Hoisting》

    Nomospace《翻译——JavaScript中的变量作用域与变量声明提升》



  • 相关阅读:
    laravel 服务提供者
    乐观锁和悲观锁
    MySQL索引原理及慢查询优化
    Laravel Session保存机制和terminate中间件
    laravel session踩坑
    理解 JavaScript 的 async/await(转)
    知识点
    js异步
    Office使用笔记
    YUM常用命令
  • 原文地址:https://www.cnblogs.com/qingguo/p/5686300.html
Copyright © 2011-2022 走看看