什么是作用域?

就是变量的有效范围。
如何检测一个变量的作用域:

  • 在指定的区域内使用这个变量,如果不报错,说明这个变量 的作用域包含此区域。

变量作用域:

function t(flag){if(flag){s="ifscope";for(var i=0;i<2;i++) ;}console.log(i);// 2
}
t(true);
console.log(s);// "ifscope"

函数作用域:

  • 只有函数能够划分变量的作用域,这种作用域的规则就叫函数作用域。

函数作用域代码:

var scope="global";
function t(){console.log(scope);//undefinedvar scope="local"console.log(scope);// "local"
}
t();

上述代码可以重写如下:

var scope="global";
function t(){var scope;console.log(scope);// undefinedscope="local"console.log(scope);// "local"
}
t();

如果在函数内访问一个变量,优先找局部变量和形参,如果没有找到,去定义该函数的环境 中查找,直到全局为止。
在 ES6 之前,只有函数可以划分变量的作用域,所以在函数的外面无法访问函数内的 变量。
在 ES6 之前,没有块级作用域的概念,所以在代码块的外面可以访问代码块内的变量.
块级作用域:凡是代码块就可以划分变量的作用域,这种作用域的规则就叫块级作用域。
块级作用域 函数作用域 词法作用域 之间的区别:

  1. 块级作用域和函数作用域描述的是,什么东西可以划分变量的作用域
  2. 词法作用域描述的是,变量的查找规则。

之间的关系:
(1)、 块级作用域 包含 函数作用域。
(2)、 词法作用域 与 块级作用域、函数作用域之间没有任何交集, 他们从两个角度描述了作用域的规则.

ES6 之前 js 采用的是函数作用域+词法作用域,ES6 js 采用的是块级作用域+词法作用域 。
详细了解可以看这篇文章

什么是变量名提升?

使用 var 关键字定义的变量,被称为变量声明;
变量声明的提升是以变量所处的第一层词法作用域为“单位”的,即全局作用域中声明的变量会提升至全局最顶层,函数内声明的变量只会提升至该函数作用域最顶层。那么开始的一段代码经过预编译则变为:

var a;
console.log(a); // undefined
a = "a";
var foo = () => {var a; // 全局变量会被局部作用域中的同名变量覆盖console.log(a); // undefineda = "a1";
}
foo();

函数声明提升的特点是,在函数声明的前面,可以调用这个函数。

console.log(foo1); // [Function: foo1]
foo1(); // foo1
console.log(foo2); // undefined
foo2(); // TypeError: foo2 is not a function
function foo1 () {console.log("foo1");
};
var foo2 = function () {console.log("foo2");
};

函数提升只会提升函数声明,而不会提升函数表达式。
js中无论哪种形式声明(var, let, const, function, function*, class)都会存在提升现象,不同的是, var,function,function*的声明会在提升时进行初始化赋值为 undefined,因此访问这些变量的时候,不会报 ReferenceError 异常,而使用 let,const,class 声明的变量,被提升后不会被初始化,这些变量所处的状态被称为“temporal dead zone”,此时如果访问这些变量会抛出ReferenceError 异常,看上去就像没被提升一样。
可以看看这文章

什么是预解析?

预解析就是在代码执行之前,先解析一部分。(要想了解预解析必须知道作用域和变量提升)
预解析之后,代码才会从上往下依次整体执行,但是预解析执行过的代码不会重复执行。
js中预解析会把声明部分的代码预先执行。

  • 声明相关的代码可以分为两部分:
  1. 变量声明 - - 通过var关键字定义的变量。
  2. 函数声明 通过 function关键字声明的函数。
    预解析时如果遇到重复的变量声明,那么忽略。
    预解析时如果遇到重复的函数声明,保留后面的函数。
    预解析时如果遇到变量与函数重名的情况,保留函数。
    对于函数内的预解析,可以理解为在执行前一瞬间进行预解析,然后再执行。
    对于参数的预解析,传参前,直接赋值undefined,传参后,就是传参的值;
    所以在函数内的预解析,参数是最先被解析到的。

举几个典型栗子(可以自己在chrome控制台输出):

alert(a);    //报错,没有var 是不会进行预解析的
a = 0;
alert(a);    //undefined
var a = 0;
alert(a);    //0, =号 可以改变初始值
alert(a);    //function a(){ alert('我是函数') },  undefined代表空,函数不是空的,当然要不是空的啦!
var a = '我是变量';
function a(){ alert('我是函数') }
alert(a);    //'我是变量', = 可以改变初始值
alert(a);    //function a(){ alert('我是函数') },  undefined代表空,函数不是空的,当然要不是空的啦!
a++;
alert(a);    //NaN, ++可以改变初始值
var a = '我是变量';
function a(){ alert('我是函数') }
alert(a)    //'我是变量', = 可以改变初始值
alert(a);    //undefined
var a = 0;
alert(a);    //0
function fn(){alert(a);    //undefined;遇到函数,重新进行预解析var a = 2;alert(a);    //2
}
fn()
alert(a);    //0,fn里面的a与全局的a不是同一作用域的
alert(a);    //undefined
var a = 0;
alert(a);    //0
function fn(){alert(a);    //0;因为没var, 所以这里的a会被看作是全局的,往上查找,找到a=0,所以是0,如果全局也没有就会报错a = 2;alert(a);    //2
}
fn()
alert(a);    //2,fn把这全局的a修改了
function fn(a){alert(a);    //undefined,JS会把传参当作var一样对待,相当于在fn内部定义了一个变量--> >var a;a = 2;alert(a);    //2,这里修改的不是全局的哦,改的是fn的局部变量哦
}
fn()
alert(a);    //报错
<script>
alert(a);    //报错,因为遇到<script>标签对时,会先对这一块进行预解析,运行到下面的>才会再进行预解析,下面没预解析,所以找不到a,于是报错了
</script><script>
alert(a);    //undefined
var a = 0;
alert(a);    //0
</script>
<script>
var a;
</script><script>
alert(a);    //undefined,虽然这个<script>标签对没有定义a,但会往上查找,上面的个<script>标签定义了,所以为undefined
</script>

再看看这几种情况:

alert(a);    //function a(){ alert('我是函数') }
function a(){ alert('我是函数') }
alert(a);    //undefined,可以看出,凡是var,初始值都是undefined
var a = function (){ '我是函数' }
function a(b){alert(b);function b(){alert(b);}b();}a(1);  //b函数, b函数
function a(b){alert(b);function b(){alert(b);}b();}a(c);  //b函数,  b函数function c(){return 123; }

javascript基础常识问答(四)相关推荐

  1. JavaScript基础练习题(四)

    JavaScript基础练习题(四) 一.单选题 1.同步和异步执行分别表示什么含义 A 同步是按顺序依次执行:异步是同时分开一起执行 B 同步是同时分开一起执行:异步是按顺序依次执行 C 同步是按一 ...

  2. javaScript基础讲义第四天(1)

    05-javaScript基础 核心知识点 数组 操作字符串方式 获取系统时间 Math相关方法 今日目标 能够完成数组相关案例 能后获取系统时间 能够操作随机数 能够完成小娜案例**[最终的目标]* ...

  3. Web前端开发精品课HTML CSS JavaScript基础教程第四章课后编程题答案

    编程题 利用这一章学到的各种文本标签,把图4-25所示的网页效果做出来. 用VS2013新建ASP.NET空网站,添加新项,建立HTML文件,向其加入以下代码: <!DOCTYPE html&g ...

  4. Jquery源码中的Javascript基础知识(四)— jQuery.fn.init方法

    $() 即调用了jQuery.fn.init方法 jQuery = function( selector, context ) {return new jQuery.fn.init( selector ...

  5. JavaScript基础学习第四天

    目标: 1. 通过循环的方式获取数组中的值,给数组赋值. 2. 能够理解为什么程序中要用数组 3. 能使用数组操作程序中的数据 ☞ 为什么要学习数组? 1. 什么是数组?: 依然是一个用来保存数据的一 ...

  6. js一行四个 超过自动换行_干货!零基础学JavaScript要掌握的四个基本常识

    零基础学JavaScript需要掌握哪几个基本常识点?下面西安鸥鹏为大家解答.了解和总结程序语言中常见的小常识,可以使编程变得容易,特别对于新手来说.JavaScript是一种弱类型客户端的编程语言, ...

  7. Javascript基础与面向对象基础~第四讲 Javascript中的类对象

    今天来说JS中如何实现类(class),事实上本应该昨天晚上写的,可我失言了,在些说一声"抱歉"!JS中的类是JS面向对象的基础,也是我最拿手的东西,你写的代码能否提高一个层次,一 ...

  8. 前端基础入门四(JavaScript基础)

    为什么80%的码农都做不了架构师?>>>    目标: 掌握编程的基本思维 掌握编程的基本语法 我们先来学习JavaScript基础,后续会讲解JavaScript高级. 自己是个做 ...

  9. 十四个关于ASP.NET基础知识问答(C#版)

    本文转自:乐猪网 十四个关于ASP.NET基础知识问答(C#版) 这是一些ASP.NET很基础的东西,希望对ASP.NET爱好者特别是刚刚入门的朋友有所帮助虽然示例代码是C#.NET,但是不影响VB. ...

  10. JavaScript基础---语言基础(1)

    写在前面: 通过四篇博客把JS基础中的基础整理一下,方便自己查阅,这些内容对于实际项目开发中也许并不会在意,但是作为JS的语言基础,自觉还是应该熟悉.在完成这三篇博客(JavaScript基础---语 ...

最新文章

  1. 让你热血沸腾的电竞直播,有一群深藏不露的技术极客
  2. 【深度学习】面向医学图像的病灶分割调研(二)
  3. LeetCode 1458. 两个子序列的最大点积(动态规划,类似编辑距离)
  4. Java Pattern类和Matcher类的使用
  5. (40)System Verilog线程停止(disable fork)
  6. LOOP AT GROUP语法熟悉
  7. THE NAUGHTY BOY
  8. Artifactory安装配置
  9. 会安装oracle数据库吗,搭建安装oracle数据库
  10. suse11 升级glibc版本
  11. RBAC 模型是什么?
  12. 索骥馆-DIY硬盘之《新手3周学通硬盘芯片级维修》扫描版[PDF]
  13. vue中watch的详细用法,带deep,immediate
  14. 计算机网络启动慢,电脑开机后网络连接图标出现的太慢了,2分钟才能出现,不出现什么都做不了,怎么办?如果手动设置...
  15. opencv——批量修改图片像素大小
  16. Linux DNS之正向解析(邮件记录、别名解析、泛域名解析)
  17. ​稳压二极管与TVS二极管
  18. 好东西下载Download
  19. Linux的Matlab使用
  20. 【MySQL】查询语句

热门文章

  1. 通过淘宝司法拍卖购买房子,需要注意些什么?
  2. SpringCloud11-GateWay网关
  3. python打错了怎么删掉_python写错了怎么删除
  4. 一个偶然发现还挺有意思的逻辑题
  5. php 加权计算公式,PHP计算加权平均数的方法
  6. 接口设计需要考虑哪些方面
  7. 计算机cpu天体图,电脑cpu天梯图2019|最新Intel/AMD处理器性能排行2019
  8. 上海宝付知识普及:个人信用到底多重要?
  9. 聊斋志异读后感 [20180818]
  10. Red5 流媒体技术(初级了解)