JavaScript作用域

1.作用域

JavaScript的作用域与C、Java等语言不同,它不是以花括号包围的块级作用域,这个特性经常被大多数人忽视。例如下面代码,在大多数类C的语言中会出现变量未定义的错误,但在JavaScript中却完全合法:

if (true) {

var msg = 'msg';

}

console.log(msg); // 输出 msg;

这是因为JavaScript的作用域完全是由函数来决定的,if、for语句中的花括号不是独立的作用域。

2.函数作用域

不同于大多数类C的语言,由一对花括号封闭的代码块就是一个作用域,JavaScript的作用域是通过函数来定义的,在一个函数中定义的变量只对这个函数内部可见,我们称为函数作用域。在函数中引用一个变量时,JavaScript会先搜索当前函数作用域,如果没有找到则搜索其上层作用域,一直到全局作用域。下面是一个简单的例子:

var scope = 'global';

var f1 = function() {

console.log(scope);

}

f1(); // 输出 global

var f2 = function() {

var scope = 'f2';

console.log(scope);

}

f2(); // 输出 f2

以上示例十分明了,JavaScript的函数定义是可以嵌套的,每一层是一个作用域,变量搜索顺序是从内到外,按照作用域搜索顺序,在console.log函数访问scope变量时,JavaScript会先搜索函数f2的作用域,恰巧在f2的作用域里搜索到了scope变量,所以上层作用域中定义的scope就被屏蔽了。但下面这个例子可能就有些让人困惑:

var scope = 'global';

var f3 = function() {

console.log(scope);

var scope = 'f3';

}

f3(); // 输出 undefined

复制代码

上面的代码可能和你的预想不一样,并没有输出global,而是undefined,这是为什么呐?这是JavaScript的一个特性,就是变量声明语句永远在该作用域里最先被执行,所以上面的例子形同如下:

var scope = 'global';

var f4 = function() {

var scope; // 变量声明最先被执行

console.log(scope);

scope = 'f4'; //变量被赋予值

}

f4(); // 输出 undefined

这样就不难理解运行f3()函数为什么没输出global,而是undefined了。

3.函数作用域的嵌套

一个作用域嵌套的例子:

var f5 = function() {

var scope = 'first';

(function() {

var scope = 'second';

(function() {

console.log(scope);

}());

}());

}

f5(); // 输出 second

我们在最内层函数中引用到了scope变量,通过作用域搜索,找到了其父作用域中定义的scope变量。

有一点要注意:函数作用域的嵌套关系是在定义时决定的,而不是在调用时决定的,下面是一个简单的例子:

var scope = 'global';

var f6 = function() {

console.log(scope);

}

var f7 = function() {

var scope = 'f7';

f6();

}

f7(); // 输出 global

这个例子中,通过f7调用的f6在搜索scope时,找到的是f6函数的父作用域中定义的scope变量,而不是f7中定义的scope变量。这说明了函数作用域的嵌套关系是在定义时决定的,而不是在调用时决定的。

Javascript的this用法

this是Javascript语言的一个关键字。

它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。比如,

function test(){

this.x = 1;

}

随着函数使用场合的不同,this的值会发生变化。但是有一个总的原则,那就是this指的是,调用函数的那个对象。

下面分四种情况,详细讨论this的用法。

情况一:纯粹的函数调用

这是函数的最通常用法,属于全局性调用,因此this就代表全局对象Global。

请看下面这段代码,它的运行结果是1。

function test(){

this.x = 1;

alert(this.x);

}

test(); // 1

为了证明this就是全局对象,我对代码做一些改变:

var x = 1;

function test(){

alert(this.x);

}

test(); // 1

运行结果还是1。再变一下:

var x = 1;

function test(){

this.x = 0;

}

test();

alert(x); //0

情况二:作为对象方法的调用

函数还可以作为某个对象的方法调用,这时this就指这个上级对象。

function test(){

alert(this.x);

}

var o = {};

o.x = 1;

o.m = test;

o.m(); // 1

情况三 作为构造函数调用

所谓构造函数,就是通过这个函数生成一个新对象(object)。这时,this就指这个新对象。

function test(){

this.x = 1;

}

var o = new test();

alert(o.x); // 1

运行结果为1。为了表明这时this不是全局对象,我对代码做一些改变:

var x = 2;

function test(){

this.x = 1;

}

var o = new test();

alert(x); //2

运行结果为2,表明全局变量x的值根本没变。

情况四 apply调用

apply()是函数对象的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象。因此,this指的就是这第一个参数。

var x = 0;

function test(){

alert(this.x);

}

var o={};

o.x = 1;

o.m = test;

o.m.apply(); //0

apply()的参数为空时,默认调用全局对象。因此,这时的运行结果为0,证明this指的是全局对象。

如果把最后一行代码修改为

o.m.apply(o); //1

运行结果就变成了1,证明了这时this代表的是对象o。

Javascript的一些经验总结的更多相关文章

  1. JavaScript 开发人员需要知道的简写技巧

    本文来源于多年的 JavaScript 编码技术经验,适合所有正在使用 JavaScript 编程的开发人员阅读. 本文的目的在于帮助大家更加熟练的运用 JavaScript 语言来进行开发工作. 文 ...

  2. 值得认真学习的6 个 JavaScript 框架

    JavaScript   JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本 ...

  3. Javascript显示和隐式类型转换

    1.转换成字符串 多数的JavaScript宿主环境(比如Node.js和Chrome)都提供了全局函数toString: 与此同时Object.prototype也定义了toString方法,使得所 ...

  4. 如何学好javascript

    今天逛论坛时看到有朋友问,是否有专门教Javascript的学校,这里想想把自己的一点建议和自己3年来的前端Javascript开发的经验跟大家分享下,也给出几本个人认为不错的书来做为大家学习的参考资 ...

  5. JavaScript显式类型转换与隐式类型转换

    隐式类型转换 四则运算 判断语句 toString 在 JavaScript 中声明变量不需指定类型,对变量赋值也没有类型检查,同时还允许隐式类型转换. 这些特征说明 JavaScript 属于弱类型 ...

  6. 各大就业网站对web前端的就业要求

    今日与女神有约,在[web前端学习部落22群]有直播公开课,喜欢的朋友赶紧加入吧!随着高等教育的普及,高校毕业生的人数每年都以极快的速度增长,数据显示,2016年,高校毕业生多达765万人,比2015 ...

  7. iOS开发60分钟入门

    原文:https://github.com/qinjx/30min_guides/blob/master/ios.md 本文面向已有其它语言(如Java,C,PHP,Javascript)编程经验的i ...

  8. 浅谈web前端就业的学习路线

    初级前端 主要学习三个部分:HTML,CSS,JavaScript 一.html + css部分: 这部分特别简单,到网上搜资料,书籍视频非常多.css中盒子模型,流动,block,inline,层叠 ...

  9. IT 名企招聘信息

    [搜狗]网页搜索抓取与挖掘组诚聘实习生 工作方向: 抓取架构方向. 职位要求  1.对互联网和搜索引擎技术有浓厚兴趣: 2.熟练使用c .熟悉Linux开发环境.熟悉shell.python.awk等 ...

随机推荐

  1. 爬虫库之BeautifulSoup学习(三)

    遍历文档树: 1.查找子节点 .contents tag的.content属性可以将tag的子节点以列表的方式输出. print soup.body.contents print type(soup. ...

  2. docker的安装与卸载

    卸载老版本docker sudo apt-get remove docker docker-engine docker.io /var/lib/docker/目录下存放着 images, contai ...

  3. PHP文件操作的经典案例

    <?php /* 遍历目录函数,只读取目录的最外层的内容 */ function readDirectory($path){ $handle = opendir($path); while(($ ...

  4. HDU - 1016 Prime Ring Problem 经典素数环

    Prime Ring Problem A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., ...

  5. CF 429B B.Working out 四个角递推

    B. Working outtime limit per test2 secondsmemory limit per test256 megabytesinputstandard inputoutpu ...

  6. HDU5997 【线段树】

    思路: 用vector存一下各种颜色的区间,每次处理颜色的区间,相同颜色不需要更新.区间最多1e6个没错,但是随着颜色的更替区间只会越来越少. 维护区间左右两端的颜色,lazy一下. 区间合并的时候 ...

  7. jzoj5986. 【WC2019模拟2019.1.4】立体几何题 (权值线段树)

    传送门 题面 题解 不难看出每个点的大小为行列限制中较小的那一个(因为数据保证有解) 对于行的每个限制,能取到的个数是列里限制大于等于它的数的个数,同理,对于列是行里大于它的个数(这里没有等于,为了避 ...

  8. ACM2017Tsukuba:H - Homework

    第一问求最多,不需要区分数学作业和信息作业,直接模拟就行了 第二问考虑每天只能产生1的贡献,每天拆成两个点,限制每天只能有1的贡献,剩下的源点连数学作业,信息作业连汇点,再将数学作业和信息作业连能连的 ...

  9. web项目数据存入mysql数据库中文乱码问题

    刚开始怀疑是项目中编码设置问题,发现在web.xml中已经有过设置:后来dubug显示数据在传输的过程中一切正常,怀疑是数据库编码问题,然后查看mysql编码: show variables like ...

  10. jdbc学习day1