javascript基础常识问答(四)
什么是作用域?
就是变量的有效范围。
如何检测一个变量的作用域:
- 在指定的区域内使用这个变量,如果不报错,说明这个变量 的作用域包含此区域。
变量作用域:
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)、 词法作用域 与 块级作用域、函数作用域之间没有任何交集, 他们从两个角度描述了作用域的规则.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中预解析会把声明部分的代码预先执行。
- 声明相关的代码可以分为两部分:
- 变量声明 - - 通过var关键字定义的变量。
- 函数声明 通过 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基础常识问答(四)相关推荐
- JavaScript基础练习题(四)
JavaScript基础练习题(四) 一.单选题 1.同步和异步执行分别表示什么含义 A 同步是按顺序依次执行:异步是同时分开一起执行 B 同步是同时分开一起执行:异步是按顺序依次执行 C 同步是按一 ...
- javaScript基础讲义第四天(1)
05-javaScript基础 核心知识点 数组 操作字符串方式 获取系统时间 Math相关方法 今日目标 能够完成数组相关案例 能后获取系统时间 能够操作随机数 能够完成小娜案例**[最终的目标]* ...
- Web前端开发精品课HTML CSS JavaScript基础教程第四章课后编程题答案
编程题 利用这一章学到的各种文本标签,把图4-25所示的网页效果做出来. 用VS2013新建ASP.NET空网站,添加新项,建立HTML文件,向其加入以下代码: <!DOCTYPE html&g ...
- Jquery源码中的Javascript基础知识(四)— jQuery.fn.init方法
$() 即调用了jQuery.fn.init方法 jQuery = function( selector, context ) {return new jQuery.fn.init( selector ...
- JavaScript基础学习第四天
目标: 1. 通过循环的方式获取数组中的值,给数组赋值. 2. 能够理解为什么程序中要用数组 3. 能使用数组操作程序中的数据 ☞ 为什么要学习数组? 1. 什么是数组?: 依然是一个用来保存数据的一 ...
- js一行四个 超过自动换行_干货!零基础学JavaScript要掌握的四个基本常识
零基础学JavaScript需要掌握哪几个基本常识点?下面西安鸥鹏为大家解答.了解和总结程序语言中常见的小常识,可以使编程变得容易,特别对于新手来说.JavaScript是一种弱类型客户端的编程语言, ...
- Javascript基础与面向对象基础~第四讲 Javascript中的类对象
今天来说JS中如何实现类(class),事实上本应该昨天晚上写的,可我失言了,在些说一声"抱歉"!JS中的类是JS面向对象的基础,也是我最拿手的东西,你写的代码能否提高一个层次,一 ...
- 前端基础入门四(JavaScript基础)
为什么80%的码农都做不了架构师?>>> 目标: 掌握编程的基本思维 掌握编程的基本语法 我们先来学习JavaScript基础,后续会讲解JavaScript高级. 自己是个做 ...
- 十四个关于ASP.NET基础知识问答(C#版)
本文转自:乐猪网 十四个关于ASP.NET基础知识问答(C#版) 这是一些ASP.NET很基础的东西,希望对ASP.NET爱好者特别是刚刚入门的朋友有所帮助虽然示例代码是C#.NET,但是不影响VB. ...
- JavaScript基础---语言基础(1)
写在前面: 通过四篇博客把JS基础中的基础整理一下,方便自己查阅,这些内容对于实际项目开发中也许并不会在意,但是作为JS的语言基础,自觉还是应该熟悉.在完成这三篇博客(JavaScript基础---语 ...
最新文章
- 让你热血沸腾的电竞直播,有一群深藏不露的技术极客
- 【深度学习】面向医学图像的病灶分割调研(二)
- LeetCode 1458. 两个子序列的最大点积(动态规划,类似编辑距离)
- Java Pattern类和Matcher类的使用
- (40)System Verilog线程停止(disable fork)
- LOOP AT GROUP语法熟悉
- THE NAUGHTY BOY
- Artifactory安装配置
- 会安装oracle数据库吗,搭建安装oracle数据库
- suse11 升级glibc版本
- RBAC 模型是什么?
- 索骥馆-DIY硬盘之《新手3周学通硬盘芯片级维修》扫描版[PDF]
- vue中watch的详细用法,带deep,immediate
- 计算机网络启动慢,电脑开机后网络连接图标出现的太慢了,2分钟才能出现,不出现什么都做不了,怎么办?如果手动设置...
- opencv——批量修改图片像素大小
- Linux DNS之正向解析(邮件记录、别名解析、泛域名解析)
- ​稳压二极管与TVS二极管
- 好东西下载Download
- Linux的Matlab使用
- 【MySQL】查询语句