作用域

词法作用域

作用域

表示的就是范围,即作用范围

  • 就是一个名字在什么地方能使用,在什么地方不能使用

块级作用域

级别的作用范围

  1. // 在 c , java 等编程语言中,下面的语法报错
  2. {
  3. var num = 123; // 应该用int , 这里是伪代码
  4. {
  5. console.log(num); // 123
  6. }
  7. console.log(num); // 报错
  8. }

在 js 中采取词法作用域

词法(代码)作用域,就是代码在编写过程中体现出来的作用范围,代码一旦写好,不用执行,他的作用范围就已经确定好了,这个就是所谓的词法作用域

在 js 中的词法作用域规则

1. 函数允许方位函数外的数据

2. 整个代码结构中只有函数可以限定作用域

3. 作用规则首先是提升规则分析

4. 就近原则如果当前作用规则有了名字,就不考虑外面的名字

在 js 中作用域分析方法

  1. 1. 先进行预解析,分析预解析过程
  2. * 程序在执行过程, 会先将代码读取到内存中检查. 会将所有的声明在此时进行标记. 所谓的标记就是
  3. js 解释器知道有这个名字, 后面在使用名字的时候, 不会出现未定义的错误. 这个标记过程就是提升.
  4. * 声明
  5. 1. 名字的声明, 标识符的声明( 变量名声明 )
  6. * 名字的声明就是让我们的解释器知道有这个名字
  7. * 名字没有任何数据与之对应
  8. 2. 函数的声明
  9. * 函数声明包含两部分
  10. * 函数声明与函数表达式有区别, 函数声明是单独写在一个结构中, 不存在任何语句, 逻辑判断等结构中
  11. * 首先函数声明告诉解释器有这个名字存在. 该阶段与名字声明一样
  12. * 告诉解释器, 这个名字对应的函数体是什么**(函数名和函数体绑定链接)**
  13. 2. 再进行代码执行过程

常见的简单作用域问题

例子 1:

  1. var num = 123;
  2. function foo(){
  3. console.log(num);
  4. }
  5. foo(); // 输出 123

分析

  1. 预解析
  1. 变量num变量名提升
  2. 函数foo函数名提升
  1. 代码执行
  1. num赋值123,函数内区域为独立区域,可以使用外部数据,但是现在变量名相同,覆盖外面的值
  2. 函数foo执行
  3. 函数区域中变量num变量名提升
  4. 输出num undefined
  5. num赋值456
  6. 输出num 456

例子 2:

  1. if(false){
  2. var num = 123;
  3. }
  4. console.log(num); // 输出undefined

分析

  1. 预解析
  1. 变量名num提升
  1. 执行代码
  1. if判断为false,不进入
  2. 输出num,num定义未赋值,为undefined

例子 3:

  1. var num = 123;
  2. function foo(){
  3. var num = 456;
  4. function fn(){
  5. console.log(num); // 输出456
  6. };
  7. fn();
  8. }
  9. foo();

分析

  1. 预解析
  1. 变量名num和函数名foo声明提升,函数名foo和函数体链接
  1. 执行代码
  1. num = 123, 赋值
  2. 执行函数, 函数内部声明提升,变量名num和函数名fn
  3. 变量num=456, 执行函数fn
  4. 输出num, fn函数内部没有num,向上级寻找
  5. num=456, 输出num

例子 4:

  1. var num = 123;
  2. function foo1(){
  3. var num = 456;
  4. function foo2(){
  5. num = 789;
  6. function foo3(){
  7. console.log(num); // 输出789
  8. }
  9. foo3();
  10. }
  11. foo2();
  12. }
  13. foo1(); // 输出456
  14. console.log(num); // 输出123

分析

  1. 预解析
  1. 变量名num和函数名foo1声明提升,函数名foo1和函数体绑定
  1. 执行代码
  1. num = 123, 赋值
  2. 执行函数foo1, 变量名num和函数名foo2声明提升, 函数名foo2和函数体绑定
  3. num = 456, 赋值
  4. 执行函数foo2, numfoo2函数中没有, 访问上级foo1得到num, num = 789, 赋值函数名foo3声明提升并且绑定函数体
  5. 执行函数foo3, 输出num, foo3中没有num,访问上级,得到num = 789
  6. 输出num789
  7. 跳出函数, 输出num123

例子 5:

  1. if ( ! 'a' in window ) {
  2. var a = 123;
  3. }
  4. console.log( a ); // undefined

分析

  1. 预解析
  1. 变量a声明提升
  1. 执行代码
  1. 判断window中是否存在a,a存在
  2. 判断为false,不执行if中的代码
  3. 输出a,为undefined

复杂的作用域问题

例子 1

  1. if ( true ) {
  2. function f1 () {
  3. console.log( 'true' );
  4. }
  5. } else {
  6. function f1 () {
  7. console.log( 'false' );
  8. }
  9. }
  10. f1();

分析

新版浏览器

  1. 预解析
  1. 无,函数f1被浏览器认为是函数表达式,不进行变量名提升
  1. 执行代码
  1. if判断进入true
  2. 执行函数表达式f1
  3. 输出结果为true

旧版浏览器

  1. 预解析
  1. 函数f1变量声明提升,f1函数名和最后一个函数体连接在一起
  1. 执行代码
  1. if判断进入true
  2. 执行f1
  3. 输出false

例子 2

  1. if ( false ) {
  2. function f1 () {
  3. console.log( 'true' );
  4. }
  5. } else {
  6. function f1 () {
  7. console.log( 'false' );
  8. }
  9. }
  10. f1();

分析

新版浏览器

  1. 预解析
  1. 无,f1为函数表达式,没有进行声明提升
  1. 执行代码
  1. if判断
  2. 执行f1
  3. 输出false

旧版浏览器

  1. 预解析
  1. 函数名f1,声明提升,函数名和最后一个函数体链接在一起
  1. 执行代码
  1. if判断
  2. 执行f1
  3. 输出false

例子 3

  1. var num = 123;
  2. function f1() {
  3. console.log( num );
  4. }
  5. function f2() {
  6. var num = 456;
  7. f1();
  8. }
  9. f2();

分析

  1. 预解析
  1. 声明提升,变量num,函数名f1,f2,函数名和函数体链接
  1. 执行代码
  1. num = 123
  2. 执行函数f2
  3. 变量num赋值456
  4. 执行函数f1
  5. 输出num,函数里面没有,向上寻找,上级为(0级作用域链),num=123,输出num123

例子 4

  1. var num = 123;
  2. function f1() {
  3. console.log( num );
  4. }
  5. function f2() {
  6. num = 456;
  7. f1(num);
  8. }
  9. f2();

分析

  1. 预解析
  1. 变量名num,函数名f1,f2声明提升,函数名和函数体链接一起
  1. 代码执行
  1. num=123
  2. 执行函数f2
  3. num=456,f2中没有num,向上级寻找得到num123,将num = 123赋值,num = 456
  4. 执行f1, f1中没有num, 向上级寻找得到num456
  5. 输出num,num=456,输出num456

JS面向对象之作用域的更多相关文章

  1. 带你一分钟理解闭包--js面向对象编程

    上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...

  2. JS面向对象(3) -- Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法

    相关链接: JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式 JS面向对象(2) -- this的使用,对 ...

  3. 原生JS面向对象思想封装轮播图组件

    原生JS面向对象思想封装轮播图组件 在前端页面开发过程中,页面中的轮播图特效很常见,因此我就想封装一个自己的原生JS的轮播图组件.有了这个需求就开始着手准备了,代码当然是以简洁为目标,轮播图的各个功能 ...

  4. js面向对象+一般方法的选项卡

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. Js面向对象编程

    Js面向对象编程 1.     什么是面向对象编程? 我也不说不清楚什么是面向对象,反正就那么回事吧. 编程有时候是一件很快乐的事,写一些小游戏,用编程的方式玩游戏等等 2.     Js如何定义一个 ...

  6. 拖拽系列二、利用JS面向对象OOP思想实现拖拽封装

    接着上一篇拖拽系列一.JavaScript实现简单的拖拽效果这一篇博客将接着对上一节实现代码利用JS面向对象(OOP)思维对上一节代码进行封装; 使其模块化.避免全局函数污染.方便后期维护和调用:写到 ...

  7. JS面向对象笔记二

    菜单导航,<JS面向对象笔记一>,  参考书籍:阮一峰之<JavaScript标准参考教程> 一.构造函数和new命令 二.this关键字 三.构造函数和new命令 四.构造函 ...

  8. 【JavaScript】 JS面向对象的模式与实践 (重点整治原型这个熊孩子 (/= _ =)/~┴┴ )

    参考书籍 <JavaScript高级语言程序设计>—— Nicholas C.Zakas <你不知道的JavaScript>  —— KYLE SIMPSON   在JS的面向 ...

  9. javascript(面向对象,作用域,闭包,设计模式等)

    javascript(面向对象,作用域,闭包,设计模式等) 1. 常用js类定义的方法有哪些? 参考答案:主要有构造函数原型和对象创建两种方法.原型法是通用老方法,对象创建是ES5推荐使用的方法.目前 ...

随机推荐

  1. 图片上传是否为空,以及类型的js验证

    function check2() { var file = document.getElementsByName("file").value; if(file=="&q ...

  2. C#三层中的分页

    最近写了一个winform的管理系统,里面的分页同学推荐了几种,感觉都不好用,比较麻烦,自己就找了一个比较简单的分页,利用数据存储过程来分页. reate proc usp_User@pageInde ...

  3. svn无法checkout大文件的解决办法

    美术组同事checkout出现,在网络好的情况下,有同事更新下来了,后来在配置文件http.conf的最后加入下面压缩参数才解决问题,配置如下: <IfModule deflate_module ...

  4. Idea IntelliJ远程调试教程

    总结 第一步:修改startup.sh 在倒第二行加上export JPDA_ADDRESS=8787 最后一行在start前面加上"   jpda   " 第二步:配置Idea, ...

  5. bzoj 1066 最大流

    将每个石柱拆成两个点,分别是进入的和出去的,两个点之间连石柱的高度 然后每个出去的点连别的石柱的进去的点, 源点连所有蜥蜴所在柱子,每个能跳出去的连汇点,然后最大流就行了 /************* ...

  6. mongodb安全

    1.流程: (1)创建超级管理员 (2)修改配置文件,验证身份登录 (3)重启服务 (4)使用超级管理员登录 (5)创建普通用户 (6)使用普通用户登录对应的数据库 mongodb数据库角色: 1创建 ...

  7. Apache服务器

    Apache服务器 一  简介 1   www:world  wide  web    万维网 http    协议:  超文本传输协议 HTML语言:  超文本标识语言 2   URL:统一资源定位 ...

  8. 关于preempt_enable 和 preempt_disable 【转】

    转自:http://blog.chinaunix.net/uid-8478094-id-2031177.html 关于preempt_enable 和 preempt_disable 允许抢占和禁止抢 ...

  9. python中deque类详解

    最近在pythonTip做题的时候,遇到了deque类,以前对其不太了解,现在特此总结一下 deque类是python标准库collections模块中的一项,它提供了两端都可以操作的序列,这意味着, ...

  10. delphi.指针.应用----应用重要 多看 多练

    来自:http://www.cnblogs.com/qiusl/p/4026459.html ----------------------------------------------------- ...