js 中的变量声明提前总结
一、var 声明
ES6之前,js 中声明变量基本上用 var 关键字;
1、如果访问未声明的变量,会报错:ReferenceError
2、声明了未赋值,值为 undefined,跟前面的报错是两回事,虽然信息看起来像;
3、对于没有声明的变量可以直接赋值,不过这是一个非常不好的习惯;
而用 var 声明的全局变量,作为全局对象的属性,是不可配置的;
4、重复声明等价于赋值语句;
JavaScript从来不会告诉你是否多次声明了同一个变量;遇到这种情况,它只会对后续的声明视而不见(不过,它会执行后续声明中的变量初始化)。
5、声明提前(hoisting)
由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量总是等效于在代码开头声明。这意味着变量可以在声明之前使用,这个行为叫做“hoisting”。“hoisting”就像是把所有的变量声明移动到函数或者全局代码的开头位置,但是 var 的赋值操作保留在原处。
声明原理:var 声明在代码执行之前,被提升到所在函数或全局环境的顶部,仅仅是声明提前,不涉及赋值操作;
总结:
在 var 声明的函数或全局环境内访问:在赋值操作之前访问,返回 undefined,不报错;在赋值操作之后访问,返回实际值,不报错;
在 var 声明的函数或全局环境外访问,报错,除非闭包;
举例:
实际上等价于:
更多例子:戳 MDN
二、let,const 声明
书上说没有声明提前,这样理解也没有问题,所以直接看 三 吧;
但是我的总结是可能有声明提前:
1、在声明的函数或全局环境内访问:
在声明的代码块之内访问:声明的位置之前访问(即使是使用 typeof),会报错(官方称”暂时性死区”);声明的位置之后访问,返回实际值;
在声明的代码块之外访问:报错(但使用 typeof 操作符不报错,返回不正确,可能为 undefined,与上述相比,证明了可能有声明提前);
2、在声明的函数或全局环境外访问,报错,除非闭包;
证明可能有声明提前的代码:
function f() {
console.log(typeof a);
if (true) {
let a = 0;
}
}
f();//undefined
下面代码报错:
function f() {
if (true) {
console.log(typeof a);
let a = 0;
}
}
f();//ReferenceError: a is not defined
下面不报错:
function f() {
if (true) {
console.log(typeof b);
let a = 0;
}
}
f();//undefined
三、函数声明语句(不是函数表达式)
声明提前原理:函数声明语句在代码执行之前,被提升到所在函数或全局环境的顶部;
总结:
在声明的函数或全局环境内访问:都返回实际值;
在声明的函数或全局环境外访问,报错,除非闭包;
实际上是跟 var 一样声明提升了,不同的是:函数整体提升,不仅仅是声明提升,而且没有块级绑定(ES6 严格模式下会有);
参考资料:
js 中的变量声明提前总结的更多相关文章
- Js中有关变量声明和函数声明提升的问题
在ECMAScript5中没有块级作用域一说,只有函数作用域和全局作用域,在其中声明的变量和函数和其他语言的展现形式不同,在某些情况下不一定需要先定义后使用,函数和变量的使用可以在其声明之前,这到底是 ...
- [JavaScript]JS中的变量声明与有效域
1.变量声明 var a = 1; //使用var声明变量 b = 1; //不使用var 第一种情况,在当前域中声明一个名为a的变量,如果实在方法内则为局部变量,若在最外层声明则a为全局变量. 第二 ...
- js函数中变量声明提前
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- js中变量声明提前
demo1: var a=10; function b(){alert(a); var a=20; alert(a)} b()//undefined 20 因为:js编译器在执行b这个函数时,会把函数 ...
- 【JS点滴】声明提前,变量声明提前,函数声明提前,声明提前的先后顺序
声明提前,函数声明提前,好吧,老生常谈的问题了.正好,前些天在掘金看到一道关于声明提前的笔试题,那么这里就以这道题来作为本文的引子吧,代码如下: console.log(a)//? a();//? ; ...
- JavaScript变量声明提前
上周四吃完午饭,leader发了一道JavaScript的题目给我们做,我们Team里面有做前端的,有做后台的,也有做mobile web的,所以大家对题目的理解各自都不一样,然后在QQ讨论组里面进行 ...
- js中的变量提升(hoisting)
来看如下代码: function HelloJS(){ var array = [1,2,3,4,5]; for(var i in array){ } alert(i); } HelloJS(); a ...
- Javascript开发技巧(JS中的变量、运算符、分支结构、循环结构)
一.Js简介和入门 继续跟进JS开发的相关教程. <!-- [使用JS的三种方式] 1.HTML标签中内嵌JS(不提倡使用): 示例:<button onclick="javas ...
- JavaScript 基础——使用js的三种方式,js中的变量,js中的输出语句,js中的运算符;js中的分支结构
JavaScript 1.是什么:基于浏览器 基于(面向)对象 事件驱动 脚本语言 2.作用:表单验证,减轻服务器压力 添加野面动画效果 动态更改页面内容 Ajax网络请求 () 3.组成部分:ECM ...
随机推荐
- ruby配置相关
1.安装ruby 方式1: yum install ruby 方式2:https://www.ruby-lang.org/en/downloads/ 使用源码安装 ./configure make m ...
- jquery获取tr并更改tr内容
jquery获取tr并更改tr内容示例代码. 例子: $(document).ready(function() { $("#Email tr").each(function(){ ...
- Windows剪贴板操作简单小例
1.复制文字到剪贴板 CString strText = L"须要拷贝到剪贴板的文字"; if ( ::OpenClipboard(m_hWnd) ) { if ( ::Empty ...
- 二叉排序树及其C代码
1.二叉排序树的定义 二叉排序树(Binary Sort Tree)又称二叉查找(搜索)树(Binary Search Tree).其定义为:二叉排序树或者是空树, 或者是满足例如以下性质的二叉树 ...
- 终端运行apk
启动一个活动 am start -n com.example.apptest/com.example.apptest.MainActivity 替换apk . udisk1/runRCApk.sh s ...
- spoj687(后缀数组)
http://www.spoj.com/problems/REPEATS/ 题意:给一串字符,需要你求这一串字符中有连续重复的字符的重复次数....... 思路:这是和poj3693一种类型的题目.. ...
- 一款基于jQuery的图片下滑切换焦点图插件
之前为大家分享了好多款jquery插件,今天我们要分享的一款jQuery插件也比较实用,是一款jQuery焦点图插件.焦点图相当普通,一共可以循环播放4张图片,并且每一张图片在切换的时候都是向下滑动的 ...
- love2d教程31--Tiled地图存档和动态修改
Advanced-Tiled-Loader有点问题,我给作者发信,可惜作者没回. 好吧,毛主席教导我们“自己动手,丰衣足食”,只好自己修改了. 1.想把0.8里的函数改为0.9的 2.添加获取对象层里 ...
- Android开发之Fragment传递參数的几种方法
Fragment在Android3.0開始提供,而且在兼容包中也提供了Fragment特性的支持. Fragment的推出让我们编写和管理用户界面更快捷更方便了. 但当我们实例化自己定义Fragmen ...
- C# 注册表修改 立即生效 [转]
修改注册表后不重启计算机边生效. const int WM_SETTINGCHANGE = 0x001A; const int HWND_BROADCAST = 0xffff; IntPtr resu ...