一直以来本人认为想深入了解一门语言,不光是让自己变成撸sir,更需要时间的锤炼。能经得起时间考验的东西更值得拥有。学习和使用Javascript一晃都7年了,最近才感觉自己对他才有顿悟,不知道是否来得有点迟。本文归纳了我对 JS中作用的理解,希望得学习有所帮助。

特别说明:这是从另一个侧面(函数域的覆盖范围)来解释和说明执行上下文。

一、作用域的理论理解

从入门Javascript时,无论是学校老师,还是你工作的老司机,都会很认真的考虑你,Js中有一个全局作用域,然后他包含很多的子域(如:由function、object创建作用域的),子域是可以很轻松的访问父级域中的任何对象。这种表述你是否感觉很是空洞,难以理解。今本人就用浩瀚无边的地域来举个粟子:

通过上面这个Image,让我一步一步带你领略作用域的魅力。

1. 首先,地球:我们大家都很熟悉,他包含着你,我,以及世界上所有的国家(这儿就不论宇宙,否则会Hold不住),这肯定就是Js中的全局作用域了。地球包含天空、空气,正如Js中全局作用包含包含Number、String、Function、Object、Boolean、Regex等对象。

2. 再者:中国、美国、朝鲜是三个平等的子作用域,他们都有利用地球 这个全局作用域的权利,如发射卫星。但美国再看不懂朝鲜,也不可能到朝鲜去干什么事情的。如Js的子作用域中可以任意使用Number、String等对象,但是没办法直接调用一个作用域平级的对象的方法。

3. 再次:你做为一个中国公民,可以依法使用中国内部的资源(只不过要么交钱买,要么就是拿了税的),如果你想买点美国的的东西,那就需要new一个什么宝、或者什么东的来做中国与美国之间的引用,然后您懂的。如Js中需要访问一个平级作用域的内容时,那你就需要拿到被访问的引用。

4. 最后:bind,apply,call,可以这样理解,bind就是在正规海购实体商场东西(预先可以看到实体的物品),而apply和call则是代购(只能视频看)。bind改变一个作用但此函数不会立刻执行,而apply和call则会立刻执行。

二、示例代码说明作用域

function Card(){
this.name = 'name';
}
Card.prototype.getName =function(callback){
callback();
return this.name;
} function PostCard(card){
this.name = "postCard"
this.card =card;
}
PostCard.prototype.getName =function(){
var _name = this.card.getName(function(){
console.log("callback: " + this.name);
});
console.log(_name + " " + this.name);
} var card = new Card();
var postCard = new PostCard(card);
postCard.getName();

1. 上述代码Card和PostCard就像第一部分提及的中国、美国一样,他们都有一个共同的父级作用域,就是window(地球)

2. Card和PostCard是平级作用域,如PostCard的getName方法想访问Card的getName方法,就需要拿到Card的引用,如PostCard构造函数传入的card实例就是为了完成这个事情。

3. Card的getName接受一个callback的高阶函数(这又是另外一个话题,函数式编程了),这里只要记住传入就是一个类型为function的形参就行了。然后在Card的getName方法中执行了callback,但这里你要注意,执行callback时没有通过任何方式或手段来指定他的作用域,所以callback执行作用域为window(地球)。

4.输出结果:

callback:
name postname

三、示例代码说明bind\apply\call

function Direction(){
this.direction = "mid";
}
Direction.prototype.set =function(val){
this.direction = val;
} var direction = new Direction();
var dir02 = new Direction();
direction.set.call(direction, "right");
direction.set.apply(dir02, ["bottom"]); console.log(direction.direction);
console.log(dir02.direction); //bind
var tmp = direction.set.bind(dir02);
tmp("bind after");
console.log('..........................');
console.log(direction.direction);
console.log(dir02.direction);

本示例代码提供了一个Direction函数,然后对this(当前实例)绑定了direction属性,且在Direction原型上绑定了set方法(用于修改this上的direction).

1. 通过 new 创建了Direction的两个实例direction,dir02

2. 通过call和apply改变作用域的指向,进行set方法的执行,call指向了direction实例,而apply指向了dir02的实例。这也展示了call与apply的区别,就是参数传送用一个列表,一个是数组。

3. 通过输出结果大家会发现,虽然都是调用direction实例的set方法,但改变的this.direction却是对应的实例属性。

4. 通过bind方法把direction实例的set方法与dir02相绑定,然后执行这个绑定,会发现改变是仍然是dir02实例的direction属性。

5. 输出结果

right

bottom
scope
..........................
right
bind after

四、作用域的总结

1. 只有一个全局作用域,但有无数个子作用域。

2. 作用域的创建与执行:

2.1 创建阶段[函数被调用,但内部代码还没开始执行]

2.2 创建 作用域链

2.3 创建变量  函数 以及参数

2.4 决定this的值(也就是作用域,或者是执行上下文)

2.5 代码执行[赋值、寻找函数引用以及解释/执行代码]

论JavaScript的作用域的更多相关文章

  1. 浅谈JavaScript的作用域

    前段时间学了下JavaScript作用域,这个东西在JavaScript非常重要,也是JavaScript很基础的东西,正如少林里面基础武功,有了基础,才能学绝世武功. 作用域的作用是啥?一套设计良好 ...

  2. JavaScript变量作用域

    全部变量拥有全局作用域,局部变量拥有局部作用域(这里注意函数的参数也是局部变量) 1.在函数体内,局部变量的优先级高于同名的全局变量. 我的理解就是当你同时定义了同名的局部变量和全局变量时,函数体内返 ...

  3. 初探JavaScript(四)——作用域链和声明提前

    前言:最近恰逢毕业季,千千万万的学生党开始步入社会,告别象牙塔似的学校生活.往往在人生的各个拐点的时候,情感丰富,感触颇深,各种对过去的美好的总结,对未来的展望.与此同时,也让诸多的老“园”工看完这些 ...

  4. JavaScript的作用域与作用域链

    作用域 作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期.可以说,变量和函数在什么时候可以用,什么时候被摧毁,这都与作用域有关. JavaScript中,变量的作用域有全局 ...

  5. JavaScript的作用域和提升机制

    JavaScript的作用域和提升机制 你知道下面的JavaScript代码执行时会输出什么吗? 1 2 3 4 5 6 7 8 var foo = 1; function bar() {     i ...

  6. Javascript的作用域、作用域链以及闭包

    一.javascript中的作用域 ①全局变量-函数体外部进行声明 ②局部变量-函数体内部进行声明 1)函数级作用域 javascript语言中局部变量不同于C#.Java等高级语言,在这些高级语言内 ...

  7. 深入理解Javascript变量作用域

    在学习JavaScript的变量作用域之前,我们应当明确几点: a.JavaScript的变量作用域是基于其特有的作用域链的. b.JavaScript没有块级作用域. c.函数中声明的变量在整个函数 ...

  8. 【转】javascript变量作用域、匿名函数及闭包

    下面这段话为摘抄,看到网上大多数人使用的是变量在使用的时候声明而不是在顶端声明,也可能考虑到js查找变量影响性能的问题,哪里用就在哪里声明,也很好. 在Javascript中,我们在写函数的时候往往需 ...

  9. 网易JS面试题与Javascript词法作用域说明

    调用对象位于作用域链的前端,局部变量(在函数内部用var声明的变量).函数参数及Arguments对象都在函数内的作用域中--这意味着它们隐藏了作用域链更上层的任何同名的属性. 2010年9月14日, ...

  10. 第一百零六节,JavaScript变量作用域及内存

    JavaScript变量作用域及内存 学习要点: 1.变量及作用域 2.内存问题 JavaScript的变量与其他语言的变量有很大区别.JavaScript变量是松散型的(不强制类型)本质,决定了它只 ...

随机推荐

  1. 难受的ESlint语法检测

    相信写过vue的各位小白都有过这样的体验,明明引入的文件语法是对的,明明自己写的代码是对的,但是总会报语法错误,没错,就是ESlint代码检测搞的鬼, 就算你在注释后面多打一个空格,它都会去搞事情,简 ...

  2. pycharm的list中copy的应用

    #拷贝的意思 li = [11,22,33,44] v = li.copy() print(v) #输出结果 [11,22,33,44] #浅拷贝

  3. redis.Redis与redis.StrictRedis区别

    redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令(比如,SET命令对应与StrictRedi ...

  4. Hadoop优化

    一.影响MR程序效率的因素 1.计算机性能: CPU.内存.磁盘.网络, 计算机的性能会影响MR程序的速度与效率 2.I/O方面 1)数据倾斜(代码优化) 2)map和reduce数量设置不合理(通过 ...

  5. Linux之环境搭建(一)

    四大系统比较 Mac OS是苹果机专用系统,是基于Unix内核的图形化操作系统,因此Unix相当于父亲,Linux和Mac OS是对兄弟. CentOS是从Redhat源代码编译重新发布版.CentO ...

  6. 《About Face 3:交互设计精髓》读书笔记(一)

    第一章 目标导向设计 当今数字产品的创造过程 市场营销人员对于产品设计过程的贡献,通常局限于需求列表这些需求同用户的实际需要与期望无关,主要在于追赶竞争对手,按照任务清单管理IT资源,以及基于市场调查 ...

  7. Makefile = ?= := 区别 $@,$^,$<

    = 是最基本的赋值:= 是覆盖之前的值?= 是如果没有被赋值过就赋予等号后面的值+= 是添加等号后面的值 1.“=” make会将整个makefile展开后,再决定变量的值.也就是说,变量的值将会是整 ...

  8. c# Winform Invoke 的用法

    在Winform中线程更新UI线程 例如:Form中有一个DataGridView,我们使用Thread查询后,更新这个表格,如果在Thread中直接更新会报错. Thread th = new Th ...

  9. 《SpringMVC从入门到放肆》十二、SpringMVC自定义类型转换器

    之前的教程,我们都已经学会了如何使用Spring MVC来进行开发,掌握了基本的开发方法,返回不同类型的结果也有了一定的了解,包括返回ModelAndView.返回List.Map等等,这里就包含了传 ...

  10. ionic4 开发企业微信应用0

    作为一个后台开发人员,几年前参与过Ionic1开发过一微信公众号的经历,所以这次开发企业微信应用,就使用了ionic,正好ionic4 rc版本发布,虽然不是正式版,作为本项目的项目经理,还是决定使用 ...