浅谈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.
特此感谢以下博主的精彩博文:
浪迹天涯《JavaScript中变量提升------Hoisting》
Nomospace《翻译——JavaScript中的变量作用域与变量声明提升》
浅谈JavaScript变量声明提升的更多相关文章
- JavaScript 变量声明提升
JavaScript 变量声明提升 一.变量提升的部分只是变量的声明,赋值语句和可执行的代码逻辑还保持在原地不动 二.在基本的语句(或者说代码块)中(比如:if语句.for语句.while语句.swi ...
- javascript变量声明提升和函数声明提升
在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域.变量提升即将变量声明提升到它所在作用域的最开始的部分. JS的解析过程分为两个阶段:预 ...
- JavaScript变量声明提升
JavaScript代码在被解析引擎执行前,会被“编译”把变量声明等放在合适的作用域中,如果不了解这一点,会让人产生很多疑惑. 文章:详解js变量声明提升
- 浅谈JS变量声明和函数声明提升
先来两个问题 很多时候,在直觉上,我们都会认为JS代码在执行时都是自上而下一行一行执行的,但是实际上,有一种情况会导致这个假设是错误的. a = 2; var a; console.log(a); 按 ...
- 谈javascript变量声明
之前的面试中遇到过一道面试题 var a =10;(function(){ console.log(a); var a =20;})() 短短5行代码log的结果是什么? 如果把var a = 20; ...
- javascript变量声明提升(hoisting)
javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面. 先看一段代码 1 2 3 4 5 var v = &quo ...
- javascript变量声明及作用域总结
javascript变量声明及作用域总结 一.总结 一句话总结:还是得好好看书,光看视频是不得行的,浅学无用,要相互印证,要真正理解才有用,比如<Javascript权威指南> 书 1.j ...
- javascript变量声明 及作用域
javascript变量声明提升(hoisting) http://openwares.net/js/javascript_declaration_hoisting.html 可能要FQ一下 java ...
- 【转】javascript变量声明 及作用域
javascript变量声明提升(hoisting) javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面. 先看 ...
随机推荐
- jquery验证前端页面
一共三个页面 jquery.html文件(前端页面,jquery验证用户信息) jquerytest.php文件(后台处理页面) jquerydb.php文件(数据库) 数据表结构 jquery.ht ...
- linux日志服务之logwatch
因为logwatch默认要使用sendmail服务,所以请参考linux之发送邮件--sendmail服务配置首先设置正确sendmail服务. 安装logwatch. 查看logwatch文件在/e ...
- 【linux高级程序设计】(第十六章)网络服务器应用设计
xinetd服务介绍 xinetd是Linux下的一个网络守候进程,用来统一管理网络负载不大的一组小型网路服务. 一些小型的网络服务,比如时间,telnet服务,不以守候进程出现,而是让xinetd服 ...
- 计蒜客 28202. Failing Components-最短路(Dijkstra) (BAPC 2014 Preliminary ACM-ICPC Asia Training League 暑假第一阶段第一场 B)
B. Failing Components 传送门 题意就是单向图,从起点开始找最短路,然后统计一下个数就可以.方向是从b到a,权值为s. 直接最短路跑迪杰斯特拉,一开始用数组版的没过,换了一个队列版 ...
- Mybatis批量添加,删除与修改
1.批量添加元素session.insert(String string,object O) public void batchInsertStudent(){ List<Student> ...
- vue插槽slot的理解与使用
一.个人理解及插槽的使用场景 刚开始看教程我的疑惑是为什么要用插槽,它的使用场景是什么,很多解释都是“父组件向子组件传递dom时会用到插槽”,这并不能很好的解决我的疑惑.既然你用了子组件,你为什么要给 ...
- 贪心+数学【p3156】 [CQOI2011]分金币 ([HAOI2008]糖果传递)
题目描述 圆桌上坐着n个人,每人有一定数量的金币,金币总数能被n整除.每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数目相等.你的任务是求出被转手的金币数量的最小值. 分析: 设: 每个人最 ...
- 使用create-react-app命令创建一个项目, 运行npm run eject报错
解决方法: 先 git add . 然后 git commit -m ‘init’ 然后再npm run eject
- 浅析Oracle PL/SQL 学习--未完待续
这是一篇关于Oracle Pl/SQL数据库编程的课程学习分享... 首先说明几点: 学习这门课程之前,已经学过并且掌握一些基础的SQL语句.数据库结构分析.ER图设计等知识: 这里也只是较为大概地将 ...
- VisualStudio Shell简介 — 集成插件
Visual Studio Shell只是提供了一个内核,我们还需要在其基础上补充功能,从而实现我们自己的IDE.Visual Studio Shell的插件开发和Visual Studio插件开发是 ...