解读JavaScript中的Hoisting机制(js变量声明提升机制)
hoisting机制:javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面。
知识点一:javascript是没有块级作用域的。函数是JavaScript中唯一拥有自身作用域的结构
知识点二:变量声明宣称一个名字的存在,变量定义则为这个名字分配存储空间,而变量初始化则是为名字分配的存储空间赋初值
知识点三:javascript中一个名字(name)以四种方式进入作用域(scope),其优先级顺序如下:
1、语言内置:所有的作用域中都有 this 和 arguments 关键字
2、形式参数:函数的参数在函数作用域中都是有效的
3、函数声明:形如function foo() {}
4、变量声明:形如var bar;
知识点四:1、函数参数是原始类型的值(数值、字符串、布尔值),传递方式是传值传递,即在函数体内修改参数值,不会影响到函数外部。
只提升变量名,不提升函数值!我是函数声明,所以我全部被提升了,包括函数名和函数体。另外,我的优先级比变量声明要高,名字和我相同的变量声明会被忽略!解析:(1)、变量a,f,b,c的声明会被提升到函数作用域的最前面,类似如下:
(function(){
var a,f,b,c;
a = "1";
f = function(){};
b = "2";
c = "3";
})();
(2)、请注意函数表达式并没有被提升,这也是函数表达式与函数声明的区别。进一步看二者的区别:
(function(){
//var f1,function f2(){}; //hoisting,被隐式提升的声明
f1(); //ReferenceError: f1 is not defined
f2();
var f1 = function(){};
function f2(){console.log('111')}
})();
上面代码中函数声明f2被提升,所以在前面调用f2是没问题的。虽然变量f1也被提升,但f1提升后的值为undefined,其真正的初始值是在执行到函数表达式处被赋予的。所以只有声明 是被提升的。
二、变量声明提升优先级实例加解说(帮助更好理解)(证明知识点三)
1、eg:(function(){
var foo;
console.log(typeof foo); //function
function foo(){}
foo = "foo";
console.log(typeof foo); //string
})();
解析:(1)、一个变量的名字与函数的名字相同,那么函数的名字会覆盖变量的名字,无论其在代码中的顺序如何。但名字的初始化却是按其在代码中书写的顺序进行的,不受以上 优 先级的影响。如果形式参数中有多个同名变量,那么最后一个同名参数会覆盖其他同名参数,即使最后一个同名参数并没有定义。知识点三名字解析优先级存在例外,比如 可以覆盖语言内置的名字arguments。
2、命名函数表达式:可以像函数声明一样为函数表达式指定一个名字,但这并不会使函数表达式成为函数声明。命名函数表达式的名字不会进入名字空间,也不会被提升。
eg:(function(){
f();//TypeError: f is not a function
foo();//ReferenceError: foo is not defined
var f = function foo(){console.log(typeof foo);};
f();//function
foo();//ReferenceError: foo is not defined
})();
解析:命名函数表达式的名字只在该函数的作用域内部有效。
3、eg:var myval = "my global var";
(function() {
console.log(myval); // "my global var"
})();
解析:将上面的例子稍作修改:
var myval = "my global var";
(function() {
console.log(myval); //"undefined"
var myval = "my local var";
})();
执行结果是输出了一个 undefined,出现这个结果的原因就是变量的声明被提升了,以上代码等同如下:
var myval = "my global var";
(function() {
var myval;
console.log(myval); //"undefined"
myval = "my local var";
})();
被提升的仅仅是变量的声明部分,并没有立即初始化,所以会输出 undefined。
4、例子3的这种提升机制,不仅仅表现于在普通的变量,同时也表现在函数上。eg:
(function() {
fun(); // Uncaught TypeError: undefined is not a function
var fun = function() {
console.log("Hello!");
}
})();
解析:上面的例子等价于:
(function() {
var fun;
fun(); // Uncaught TypeError: undefined is not a function
fun = function() {
console.log("Hello!");
}
})();
因为函数的声明同样被提升而没有立即初始化,所以会出错。
当然,这种定义函数的方式称之为“函数表达式”,会有提升机制,如果是如下的这种“函数声明”方式,则完全没有提升机制方面的问题:
(function() {
fun();
function fun() {
console.log("Hello!"); //"Hello!"
}
})();
这也是函数声明与函数表达式的主要区别。
三、函数传参变量提升问题(证明知识点四)
1、eg:var foo=1;
(function (foo) {
console.log(foo);//1
foo=3;
var foo=2;
console.log(foo);//2
})(foo);//1
console.log(foo);
解析:函数参数是原始类型的值(数值、字符串、布尔值),传递方式是传值传递,即在函数体内修改参数值,不会影响到函数外部。
2、eg:var foo={n:1};
(function (foo) {
console.log(foo.n);//1
foo.n=3;
var foo={n:2};
console.log(foo.n);//2
})(foo);
console.log(foo.n);//3
解析:函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递,传入的是原始值的地址,因此在函数内部修改参数,将会影响到原始值。
3、eg:var foo={n:1};
(function (foo) {
console.log(foo.n);//1
foo = {n:3};
var foo={n:2};
console.log(foo.n);//2
})(foo);
console.log(foo.n);//1
解析:如果函数内部修改的,不是参数对象的某个属性,而是替换掉整个参数,这时不会影响到原始值!
4、eg:var foo = {n:1};
(function(foo){ //形参foo同实参foo一样指向同一片内存空间,这个空间里的n的值为1
var foo; //优先级低于形参,无效。
console.log(foo);
console.log(foo.n); //输出1
foo.n = 3; //形参与实参foo指向的内存空间里的n的值被改为3
foo = {n:2}; //形参foo指向了新的内存空间,里面n的值为2.
console.log(foo.n); //输出新的内存空间的n的值
})(foo);
console.log(foo.n); //实参foo的指向还是原来的内存空间,里面的n的值为3.
答案:{n:1} ,1,2,3
解读JavaScript中的Hoisting机制(js变量声明提升机制)的更多相关文章
- js变量声明提升
1.变量提升 根据javascript的运行机制和javascript没有块级作用域这个特点,可以得出,变量会声明提升移至作用域 scope (全局域或者当前函数作用域) 顶部的. 变量声明提升至全局 ...
- js中全局变量和局部变量以及变量声明提升
javascript中全局变量和局部变量的区别 转载前端小99 发布于2018-04-23 15:31:35 阅读数 2102 收藏 展开 [javascript] view plain copy ...
- 详解js变量声明提升
之前一直觉会认为javascript代码执行是由上到下一行行执行的.自从看了<你不知道的JS>后发现这个观点并不完全正确.先来给大家举一个书本上的的例子: var a='hello wor ...
- Js 变量声明提升和函数声明提升
Js代码分为两个阶段:编译阶段和执行阶段 Js代码的编译阶段会找到所有的声明,并用合适的作用域将它们关联起来,这是词法作用域的核心内容 包括变量声明(var a)和函数声明(function a(){ ...
- 关于Javascript没有块级作用域和变量声明提升
Javascript是没有块级作用域的,在语句块中声明的变量将成为语句块所在代码片段的局部变量.例如: if(true){ var x=3; } console.log(x); 结果输出3. 再如: ...
- JS变量声明提升和函数声明提升
JS代码在执行的时候会先找出执行代码中定义的变量和函数,对其进行声明. 例1:console.log(a); var a = 4; 此时输出undefined.a变量在执行console.log(a) ...
- JavaScript中的陷阱(关于变量声明,函数)
查看:http://www.css88.com/archives/5347#more-5347
- JavaScript变量声明提升
JavaScript代码在被解析引擎执行前,会被“编译”把变量声明等放在合适的作用域中,如果不了解这一点,会让人产生很多疑惑. 文章:详解js变量声明提升
- JavaScript中var和this定义变量的区别
JavaScript中var和this定义变量的区别 在js中声明变量时可以使用var和this,但使用this的有很大一部分参考书是没有的,经过查阅相关资料总结如下: 用var和this声明变量,存 ...
随机推荐
- mysql应用学习-在cmd命令窗口下创建数据库和表
运行以下操作,请确认您已经正确安装和配置了mysql. 首先要运行cmd.exe,进入命令窗口. step1. 进入MySQL monitor 如果您已登录mysql,可直接进入step2;若未登录请 ...
- 彻底消除wine中文乱码,QQ,kugoo等等....
原文链接:http://forum.ubuntu.org.cn/viewtopic.php?t=290155 lendylongli wine下中文的配置方案步骤:1. 初始设置运行 winecfg, ...
- SSO单点登录三种情况的实现方式详解(转)
https://blog.csdn.net/ainuser/article/details/65631713
- flex布局的一些注意点
现在来总结下自己在项目中用flex布局的一些注意点 1.ui图中的布局方式与justify-content的布局方法不一样 这是就要利用flex-grow的空dom来分开子容器来达到页面布局的效果 2 ...
- 学习 JavaScript 树
学习 JavaScript 树 树(Tree) 在计算机科学中,数据结构是一门研究非数值计算的程序设计问题中计算机的操作对象(数据元素)以及它们之间的操作和运算等的学科. 它包含三方面的内容: 数据的 ...
- 基本算法思想Java实现的详细代码
基本算法思想Java实现的详细代码 算法是一个程序的灵魂,一个好的算法往往可以化繁为简,高效的求解问题.在程序设计中算法是独立于语言的,无论使用哪一种语言都可以使用这些算法,本文笔者将以Java语言为 ...
- 浅谈SQL Server中的事务日志(五)----日志在高可用和灾难恢复中的作用
简介 日志的作用是保证持久性和数据一致性,通过日志可以实现数据的Undo与Redo,因此通过日志,SQL Server不仅仅可以实现灾难恢复,还可以通过日志的Redo来实现高可用性.本篇文章主要讲述日 ...
- maven学习(三)maven仓库
官网图片: maven仓库: 仓库通常配置在settings.xml文件中,此处注意settings.xml的优先级:用户 > 全局,广义上maven的仓库一共包含两种: 1.本地仓库,默认在& ...
- Siebel计划和实施
1.计划: 自上而下计划配置项目 1)首先,确定UI和应用产品功能 2)然后,确定为实现UI功能而需要在业务层所做的更改 3)最后,确定为实现业务层更改而需要在数据层所做的更改---尽可能少做更改 如 ...
- 获取v$latch数据源实验
实验环境:Oracle Rac 11.2.0.3 首先获取v$latch的定义:通过PL/SQL或者get ddl等常规途径只能获取到v_$latch相关的视图信息.需要通过特殊方法获取v$latch ...