JavaScript中的作用域与函数和变量声明的提升
var foo = 1;
function bar() {
if (!foo) {
var foo = 10;
}
alert(foo);
}
bar();//解释:js没有块级作用域,if switch while等不会有块级作用域
如果你对foo的值实际上为"10"而感到诧异的话,再看一下下面这个例子:
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
发现浏览器会弹出alert(1)。
//解释:第一点是函数声明的提升会把函数的实现都提升到作用域的最顶级,上面的函数b相当于
function b() {
function a() {}
a = 10;
return;
}
第二点是:这样的话,我们在b函数里面定义了一个a函数,a的作用域是在b函数的内部而非全局,这是对a的赋值相当于把a函数替换,作用域并不发生变化,相当于用var定义了一个a变量;所以在b函数外面输出a的时候只会去访问全局的a;
//var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);//报错a is undefined
另外:如果这里的a函数不是函数声明式定义的而是变量式定义的,变量提升而函数实现并不会提升:如下:
var a = 1;
function b() {
a = 10;
return;
a=function () {} //此处的a是全局的变量
}
b();
alert(a);//10
如果是这样的话
var a = 1;
function b() {
a = 10;
return;
var a=function () {} //此处的a是局部变量
}
b();
alert(a);//1
等价于这个:
var a = 1;
function b() {
var a;
a = 10;
return;
a=function () {} //此处的a是局部变量
}
b();
alert(a);//1
可以发现,声明语句中的赋值部分并没有被提升声明,只有名称被提升了。两种函数声明方式:
function test() {
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
}
test();
这个例子中,只有包含函数体的函数声明会被提升声明。foo虽然会被提升声明,但是函数体却在执行中被赋值。以上就是提升声明时机的基本概念,看起来一点也不复杂。 Name resolution order(JavaScript中名称解析顺序) 名称解析顺序有4步,一般来说,如果一个名称已经被定义了,它就不会被另一个具有同名称的属性所覆盖。这也就意味着,函数声明会比变量声明优先。并不是名称的赋值操作不会被执行,只是说声明部分被忽略了而已。有些例外:
- 原生变量
arguments
特立独行,包含了传递到函数中的参数。如果自定义以arguments
为命名的参数,将会阻止原生arguments
对象的创建。所以勿使用arguments
为名称的参数。 - 胡乱使用
this
标识符会引起语法错误。 - 如果多个参数具有相同的命名,那么最后一个参数会优先于先前的,即时这个参数未定义。
Named Function Expressions(函数命名表达式) 你可以通过函数表达式给函数命名,语法上看起来像是函数声明,实则不是。上一段代码:
foo(); // TypeError "foo is not a function"
bar(); // valid
baz(); // TypeError "baz is not a function"
spam(); // ReferenceError "spam is not defined"
var foo = function () {}; // anonymous function expression ('foo' gets hoisted)
function bar() {}; // function declaration ('bar' and the function body get hoisted)
var baz = function spam() {}; // named function expression (only 'baz' gets hoisted)
foo(); // valid
bar(); // valid
baz(); // valid
spam(); // ReferenceError "spam is not defined"
JavaScript中的作用域与函数和变量声明的提升的更多相关文章
- javascript中var let const三种变量声明方式
javascript中var let const三种变量声明方式 1.var ①var表示声明了一个变量,并且可以同时初始化该变量. ②使用var语句声明的变量的作用域是当前执行位置的上下文:一个函 ...
- Javascript中函数及变量定义的提升
<html> <head> <title>函数提升</title> <script language="javascript" ...
- JavaScript中的作用域
很多(JavaScript)开发者都在讨论"作用域",但它是什么?它们在JavaScript中的任何地方!我发现很多年轻的开发者不知道作用域是什么.他们中大多数人可以用jQuery ...
- [转]Javascript中的自执行函数表达式
[转]Javascript中的自执行函数表达式 本文转载自:http://www.ghugo.com/javascript-auto-run-function/ 以下是正文: Posted on 20 ...
- 深入理解javascript中的立即执行函数(function(){…})()
投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014-06-12 我要评论 这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是 ...
- 【翻译】JavaScript中的作用域和声明提前
原文:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ===翻译开始=== 你知道下面的JavaScript脚本执 ...
- JavaScript中的作用域和闭包
首先强烈安利<你不知道的JavaScript>,JS初学者进阶必读. 对于从C++.Java等静态语言转向JavaScript的初学者(比如我)来说,JS一些与众不同而又十分要紧的特性使得 ...
- JavaScript中的作用域和声明提前
[翻译]JavaScript中的作用域和声明提前 原文:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ===翻译 ...
- javascript中的立即执行函数(function(){…})()
javascript中的立即执行函数(function(){…})() 深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是用(function(){…})()包 ...
随机推荐
- e2e 自动化集成测试 架构 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (五) 如何让窗体记录登录状态Session
在写自动化测试的Node.js脚本时, 时常需要测试所写的case, 可能都需要去重新登录一遍,这将相当的耗时, 好在Selenium都借了Session的机制, 如果在最初的浏览器没有关闭的情况下, ...
- 刷票 变 IP
刷票 变 IP
- bzoj 1176 Mokia(CDQ分治,BIT)
[题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=96974 [题意] 定义查询操作与修改操作:1 x y z 为 ...
- NOIP2010 引水入城
4引水入城 题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N 行M 列的矩形,如上图所示,其中每个格子都代表一座城市,每座城市都有一个 ...
- 2016"百度之星" - 复赛(Astar Round3) 1003 拍照
拍照 思路:先静态,离线树状数组,分别统计每个点向左向右能看到的船的数量.再枚举整个区间求最大值. 应为人和船都是动态的,假设船往左走,处理每个点看到向左最大船的数量,满足动态条件.就是向左的船一开始 ...
- rpc,客户端与NameNode通信的过程
远程过程:java进程.即一个java进程调用另外一个java进程中对象的方法. 调用方称作客户端(client),被调用方称作服务端(server).rpc的通信在java中表现为客户端去调用服务端 ...
- Ubuntu 14.04.3 LTS 配置 DNS Server
我们目的是用一台局域网机器完成 192.168.1.113 <-->cloudshield.com的解析,指定A记录和CNAME; 0.关于Ubuntu 14.04.2 LTS 下载.安装 ...
- homework-02 一坑到底的最大和联通图
你在这个作业中学到了什么? 有什么好的设计值得分享? 感想如何 (太容易 / 太难 / 太无趣)? 我觉得这套题目有点偏难,我不像大牛那样,有很多算法可以选择,我是0算法基础的,所以遇到这题我一个 ...
- Java网络编程(UDP协议-聊天程序)
接收端: package WebProgramingDemo; import java.net.DatagramPacket; import java.net.DatagramSocket; publ ...
- HDU 4628
这是一个大水题啊... 因为比赛时不会算复杂度耽误半天. i从0到2^n枚举集合i的所有分割两半的情况的复杂度为O(3^n),可以想象这个过程相当于是给每个位标记0,1,2(0表示不选,1,2表示两个 ...