javascript函数跟变量的声明、作用域这些概念网上都已经讲烂了。

这里写个博客,也相当于做个笔记。

变量声明

首先看个例子:

var globalVar = "gv";
function fc() {
console.log(globalVar);
var globalVar = "lv";
console.log(globalVar);
}
fc();

这个例子输出:

undefined

"lv"

为什么会输出这样的信息呢?

  javascript中变量声明会被预编译(自动调整)到所在代码作用域的顶部。 原来那段代码将会变成仅仅给变量赋值的操作。

上面的代码也就变成了下面的代码。

var globalVar = "gv";
function fc() {
var globalVar;
console.log(globalVar);
globalVar = "lv";
console.log(globalVar);
}
fc();
函数体内的   var globalVar = "lv";  这段代码被拆分成了2个部分。
--- 第1个部分就是我们要说的var globalVar,也就是变量声明,它被预编译到所在作用域的顶部;第2部分就是给变量赋值操作。
因此,第一个console输出的是undefined(因为globalVar仅仅声明了,为赋值,声明的变量javascript会给个undefined值) ;
第二个输出的是“lv”,因为此时globalVar已经被赋值了。 现在你可能会问。 我在函数fc之外已经定义了1个全局变量globalVar, 并且fc函数内部我也仅仅再次声明了这个变量, 并没有赋值, 照理说应该会使用函数外的全局变量的。 为什么执行的时候却找不到呢。 照理说应该会输出 "gv" "lv" 的。 这是因为globalVar在函数体内通过关键字var声明了,这表示这个globalVar在函数体是是一个局部变量。
如果我们将函数体内的globalVar前面的var关键字去掉:
var globalVar = "gv";
function fc() {
console.log(globalVar);
globalVar = "lv";
console.log(globalVar);
}
fc();

那么就会输出"gv"  "lv"。  因为函数体内的globalVar是一个全局变量。

作用域

javascript的作用域有2种。1个全局作用域,1个是函数作用域。 它没有块级作用域
全局作用域很好理解, 在代码中任何地方都能访问到的对象拥有全局作用域。
函数作用域就是在函数体内声明的一些函数,变量。 那么什么是块级作用域呢?
首先,来看个例子:
for(var i = 0; i < 5; i ++) {
var j = i;
}
console.log(i +', ' + j); switch(j) {
case 4: var k = 2; break;
default: var k = 3;
} console.log(k); if(i >= 5) {
var l = 6;
} console.log(l);
这里例子最后都会输出i,j,k,l的值, 值分别为5、4、2、6。 
说明了javascript是没有块级作用域。for、if、switch等关键字包括起来的{}这段代码就是所谓的块级作用域。
结果还是可以找出这4个变量, 并没有报错。
没有块级作用域,那么以上代码就是在全局作用域内定义并执行的。
本文一开始讲了变量声明的预编译。 预编译的作用范围其实是在作用域里才会起作用的。
于是。 块级作用域的例子进行预编译之后会是如下样子:
var i,j,k,l;

for(i = 0; i < 5; i ++) {
j = i;
}
console.log(i +', ' + j); switch(j) {
case 4: k = 2; break;
default: k = 3;
} console.log(k); if(i >= 5) {
l = 6;
} console.log(l);

函数声明

函数声明同样会被提取到当前作用域内的最前面。

console.log(func);
function func() {
console.log(1);
}

以上这段代码就会输出func这个函数的定义代码。 而不是undefined。

函数声明与变量声明的优先级

如果我一段代码中既有函数声明,又有变量声明,那么谁的优先级更高呢?

          答案是:变量声明。

即变量声明的优先级比函数声明的优先级要更高

但是这个定义是有条件的。

function func() {
console.log(1);
}
var func = 1;
console.log(func);
var func = 1;
function func() {
console.log(1);
}
console.log(func);

这两段代码都会输出 1 。 说明的变量声明的优先级比函数声明高,也就是说变量声明会覆盖函数声明。

下面再来看个例子:

var func;
function func() {
console.log(1);
}
console.log(func);

这里会输出func函数的定义,不会输出undefined。

因为这段代码中变量声明并未进行赋值操作, 仅仅声明了1个变量。

因此最准确的说法是:  进行赋值操作的变量声明的优先级比函数声明要高。

总结

javascript是一门非常奇葩的语言,里面的坑其实蛮多的。

但是只要掌握好基础,其实也还好吧。

参考资料:

http://www.cnblogs.com/snandy/archive/2012/03/01/2373237.html

http://www.cnblogs.com/TomXu/archive/2011/12/28/2286877.html

浅谈javascript函数,变量声明及作用域的更多相关文章

  1. 浅谈javascript函数节流

    浅谈javascript函数节流 什么是函数节流? 函数节流简单的来说就是不想让该函数在很短的时间内连续被调用,比如我们最常见的是窗口缩放的时候,经常会执行一些其他的操作函数,比如发一个ajax请求等 ...

  2. [转载]浅谈JavaScript函数重载

     原文地址:浅谈JavaScript函数重载 作者:ChessZhang 上个星期四下午,接到了网易的视频面试(前端实习生第二轮技术面试).面了一个多小时,自我感觉面试得很糟糕的,因为问到的很多问题都 ...

  3. 浅谈JavaScript 函数作用域当中的“提升”现象

    在JavaScript当中,定义变量通过var操作符+变量名.但是不加 var 操作符,直接赋值也是可以的. 例如 : message = "hello JavaScript ! " ...

  4. 浅谈javascript函数执行过程

    javascript函数执行过程: 1. 为函数创建一个执行环境 2. 复制函数的 [[scopes]] 属性中的对象构建起执行环境的作用链域 3. 创建函数活动对象并推入执行环境作用链域的前端 4. ...

  5. [转]浅谈javascript函数劫持

    转自:Ph4nt0m Security Team 这么多年了,现在学习依然还是有很多收货,向前辈致敬.转载一方面是自己存档一份,另一方面是让更多喜欢安全的人一同学习. ================ ...

  6. 浅谈C语言变量声明的解析

    C语言本身提供了一种不甚明确的变量声明方式——基于使用的声明,如int *a,本质上是声明了*a的类型为int,所以得到了a的类型为指向int的指针.对于简单类型,这样声明并不会对代码产生多大的阅读障 ...

  7. 浅谈javascript中变量作用域和内存(2)

    1.无块级作用域 javascript没有块级作用域,这会让其他程序员在理解js代码上很痛苦.在其他很多语言,比如C,大括号括起来的代码块都有自己的作用域 举个例子 if(true) { var na ...

  8. 浅谈javascript的变量作用域

    1.变量遵循先声明再使用. console.log(b); b=123; 代码运行结果: Uncaught ReferenceError: b is not defined 2.方法内定义的局部变量外 ...

  9. 浅谈javascript中变量作用域和内存(1)

    先理解两个概念:基本类型和引用类型的值 1.基本类型和引用类型的值 (1)定义: 基本类型:指简单的数据段,比如按值访问的js五种基本数据类型undefined.null.boolean.number ...

随机推荐

  1. WebApi 插件式构建方案:IOC 容器初始化

    body { border: 1px solid #ddd; outline: 1300px solid #fff; margin: 16px auto; } body .markdown-body ...

  2. solr特点九:word(分词)

    在Solr中配置中文分词IKAnalyzer 1.在配置文件schema.xml(位置{SOLR_HOME}/config/下),配置信息如下: <!-- IKAnalyzer 中文分词--&g ...

  3. gitignore 使用

    在git中如果想忽略掉某个文件,不让这个文件提交到版本库中,可以使用修改根目录中 .gitignore 文件的方法(如无,则需自己手工建立此文件).这个文件每一行保存了一个匹配的规则例如: # 此为注 ...

  4. Angular之constructor和ngOnInit差异及适用场景

    constructor会在类生成实例时调用,Angular无法控制constructor,constructor中应该只进行依赖注入而不是进行真正的业务操作 ngOnInit属于Angular生命周期 ...

  5. winform app.cpnfig 文件的引用

    1.app.config配置文件修改 <?xml version="1.0" encoding="utf-8"?> <configuratio ...

  6. ASP.NET WebApi总结之自定义权限验证

    在.NET中有两个AuthorizeAttribute类, 一个定义在System.Web.Http命名空间下 #region 程序集 System.Web.Http, Version=5.2.3.0 ...

  7. yum 下载RPM包而不进行安装

    yum命令本身就可以用来下载一个RPM包,标准的yum命令提供了--downloadonly(只下载)的选项来达到这个目的. $ sudo yum install --downloadonly < ...

  8. “全栈2019”Java异常第八章:throw关键字详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  9. Mybatis 动态Sql语句《常用》

    MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦.拼接的时候要确保不能忘了必要的空格,还要注意省掉 ...

  10. RN 中 Native 模块的注入过程

    找到所有的模块 一般来说,只要在模块中声明 RCT_EXPORT_MODULE 即可.这是个宏,展开后是声明了一个函数,定义了两个函数,如下所示. #define RCT_EXPORT_MODULE( ...