在ECMAScript5中没有块级作用域一说,只有函数作用域和全局作用域,在其中声明的变量和函数和其他语言的展现形式不同,在某些情况下不一定需要先定义后使用,函数和变量的使用可以在其声明之前,这到底是怎么回事呢?让我们一起揭开变量声明提前的神秘面纱!!!

一、变量声明提升

 var a = 10;
function test() {
a = 100;
alert(a);
alert(this.a);
var a;
alert(a);
}
test();

这题考的也是变量声明提升,函数作用域中提前使用变量时一定要注意下面是否有利用var声明,如果有会将其提升,而不是使用外面的全局变量。相当于如下代码:

 var a = 10;
function test() {
var a;
a = 100;
alert(a);//
alert(this.a);//
alert(a);//
}
test();
//所以输出的结果是 100 10 100

同时要注意在同一作用域内利用var定义多个同名变量如果后面没有赋值,这该变量的值仍是上一次所附的值,如下:

 var a = 100;
var a;
console.log(a) //

二、函数的声明提升

先上题,看看下体应该输出的结果是什么:

(1)第一题:

 f = function () { return true; };
g = function () { return false; };
(function () {
if (g() && [] == ![]) {
f = function f() { return false; };
g = function() { return true; }
}
})();
alert(f());

输出的结果是true ,函数的声明会被提前,但是函数表达式是不会被提前的,在if条件判断中的f和g均为函数表达式,所以均不会被提前,使用全局的变量进行判断,,if中的结果如下:

 var s1 = g();//false
var s2 = g() && []; //false
var s3 = ![]; //false
var s4 = g() && [] == ![]; //false(此处注意运算符的优先级条件运算符的优先级高于逻辑运算,所以先执行后面的,在执行前面的)
var s5 = (g() && []) == ![]; //true
//所以最后的结果为true。

(2)如果将上面的稍作改变结果会是怎样呢?

 f = function () { return true; };
g = function () { return false; };
(function () {
if (g() && [] == ![]) {
f = function f() { return false; };
function g() { return true; } //(1)
}
})();
alert(f());

此题中if中的g函数的声明会被提前,但是定义不会被提前(这个下面将会提到),所以if中使用的将不会 是全局的函数g,而是局部变量,但是虽然g进行了声明,但是没有定义故会报错g is not a function 。如果将(1)式变为 var g = function(){};这样也会报同样的错误,但是后者相当于是函数表达式,提升的是var定义的变量而不是函数的声明,这一点要注意区分的。

三、经过上面的练习你一定好奇函数的声明提前到底是怎么回事,下面我们就函数的声明和定义提前好好聊聊(此处将排开函数表达式,因为函数表达式是不会被提前的)

ES5中有规定不要将函数定义在语句块中,也就是函数可以在全局作用域和函数作用域中被声明和定义,但不要在if等语句块中当定义和声明。在全局和函数作用域中定义的函数的声明和定义豆浆会被提前到当前作用域的顶部。但是if,和for中声明的函数在非严格模式下不会报错,但是不同的浏览器可能表现不同。在谷歌中,在if 等语句块中声明的函数的声明会被提前但是函数的定义将不会被提前。所以在块语句里面最好是使用函数表达式,而不是函数的声明。

(1)   函数的声明和定义均被提前到当前作用域的顶部

 f();
function f(){
console.log("ok")
}
// 输出结果ok 函数的声明和定义均被提前

(2)IIFE中定义的函数(相当于函数中定义的函数)

 (function(){
f();
function f (){
Console.log(“hello”)
}
})()
//输出的结果是 hello

(3)if块中定义的函数

 console.log(f)
f();
if(false){
function f(){
console.log("ok")
}
} //输出undefined后,报错f is not a function 说明在if语句块中的函数的声明被提前但是函数的定义没被提前

(4)for语句块中定义的函数

 1 console.log(f)
2 f()
3 for(f();false;){
4 function f(){console.log("ok")}}
5 //输出undefined后,报错f is not a function 说明在for语句块中的函数的声明被提前但是函数的定义没被提前

以上便是个人对变量提升的见解如有不足之处,请指教

转载请注明出处:http://www.cnblogs.com/heshan1992/p/7262387.html

Js中有关变量声明和函数声明提升的问题的更多相关文章

  1. [js]变量声明、函数声明、函数定义式、形参之间的执行顺序

    一.当函数声明和函数定义式(变量赋值)同名时 function ledi(){ alert('ledi1'); }; ledi(); var ledi = function (){ alert('le ...

  2. JavaScript 中定义变量时有无var声明的区别

    关于JavaScript中定义变量时有无var声明的区别 var a=5; //正确 a=5; //正确 在javascript中,以上两种方法都是定义变量的正确方法.微软的Script56.CHM中 ...

  3. js中的变量提升和函数提升

    从上周开始,我所在的学习小组正式开始了angular的学习,angular是全面支持es6的,所以语法上和以前的angular有了很大的不同,比如变量声明时就抛弃了var,而选择了let和const: ...

  4. js中局部变量必须用var去声明

    js中的变量与其他的脚本语言都是很不一样的,在function中你如果不用var 声明一个变量,那么这个变量将在全局可见,也就相当于创建了全局变量.所以在function中声明变量尽量都是用var来声 ...

  5. javaScript的函数(Function)对象的声明(@包括函数声明和函数表达式)

    写作缘由: 平时再用js写函数的时候,一般都是以惯例 function fn () {} 的方式来声明一个函数,在阅读一些优秀插件的时候又不免见到 var fn = function () {} 这种 ...

  6. JS中的循环嵌套 BOM函数

    [嵌套循环特点]                           外层循环转一次,内层循环转一圈              外层循环控制行数,内层循环控制每行元素个数             [做 ...

  7. Javascript开发技巧(JS中的变量、运算符、分支结构、循环结构)

    一.Js简介和入门 继续跟进JS开发的相关教程. <!-- [使用JS的三种方式] 1.HTML标签中内嵌JS(不提倡使用): 示例:<button onclick="javas ...

  8. JavaScript 基础——使用js的三种方式,js中的变量,js中的输出语句,js中的运算符;js中的分支结构

    JavaScript 1.是什么:基于浏览器 基于(面向)对象 事件驱动 脚本语言 2.作用:表单验证,减轻服务器压力 添加野面动画效果 动态更改页面内容 Ajax网络请求 () 3.组成部分:ECM ...

  9. JS中的变量和输入输出

    一.使用JS的三种方式 1.在HTML标签中,直接内嵌JS(并不提倡使用) <button onclick="alert('点你咋地')">点我</button& ...

  10. JS中的日期内置函数

    用JS中的日期内置函数实现在页面显示:“今天是:2013年9月26日14:32:45”. var date=new Date(Date.parse('9/26/2013 14:32:45'));   ...

随机推荐

  1. XWindow启动流程

    X Window系统架构 一.基本概念: 1.X Client:X客户端,运行在远端主机上 X Client最重要的工作就是处理来自 X Server 的动作,将该动作处理成为绘图数据, 再将这些绘图 ...

  2. [转]AngularJS 之 ng-options指令

    原文地址 一. 基本下拉效果(lable for value in array) 其中select标签中的ng-model属性必须有,其值为选中的对象或属性值. <div ng-controll ...

  3. maven 的docker插件

    首先你得配置一个带有认证的docker私有仓库. 本机要安装maven和jdk vi pom.xml <plugin> <groupId>com.spotify</gro ...

  4. SICP-2.2-数据的抽象

    数据的抽象 生活中有许多的事物具有复合结构,例如地理位置所用的经纬度,便是通过一个复合结构来代表位置,在我们的程序当中,我们设法将经度纬度组合成一对,我们既可以把他们当做一个整体单元来进行操作,而且也 ...

  5. EntityFramework连接SQLite

    EF很强大,可惜对于SQLite不支持CodeFirst模式(需要提前先设计好数据库表结构),不过对SQLite的数据操作还是很好用的. 先用SQLiteManager随便创建一个数据库和一张表:

  6. Swift字符串可变性

    您可以通过将一个特定字符串分配给一个变量来对其进行修改,或者分配给一个常量来保证其不会被修改: var variableString = "Horse" variableStrin ...

  7. Chapter 6. H.264/MPEG4 Part10

    本章节主要介绍有关H.264的内容 H.264有三种profile,分别是: Baseline Profile Main Profile Extended Profile 三者之间的关系和主要内容可以 ...

  8. java桥连接sql server之登录验证及对数据库增删改查

    一:步骤 1.sql server建立数据库和相关表 2.建立数据源  (1).打开控制面板找到管理,打开ODBC选项或直接搜索数据源  (2).打开数据源配置后点击添加,选择sql server点击 ...

  9. 【PHP】制作日历

    本期本博主将讲述两种利用PHP制作日历的方法,由于PHP日期函数的便捷性,使得我们制作日历这一过程变得相当简单 问题描述: 1.取到当前日期,并着色显示:2.根据当前日期,判断本月有多少天,一号是周几 ...

  10. accp8.0转换教材第3章MySQL高级查询(一)理解与练习

    一.单词部分 ①constraint约束②foreign外键③references参考 ④subquery子查询⑤inner内部的⑥join连接 二.预习部分 1.修改表SQL语句的关键字是什么 RE ...