一、变量作用域
说到这个概念,不有自主的想到this,scope 这两个关键字。

JavaScript的this总是指向一个明确的对象,这个对象是在执行的时候动态绑定的。通俗的说就是谁调用我,我的this就是谁。
除去不常用的with和eval,具体的实际应用中,this的指向分为以下四种情况:

·作为对象的调用;
·作为普通函数的调用;
·构造器的调用;
·Function.propotype.call 和 Functio.propotype.apply 调用;

下面我们分别进行介绍。

1、作为对象的调用
当函数作为对象的方法被调用时,this指向这个对象:

var obj={
a:1,
getA:function(){
alert(this===obj);
alert(this.a);
}
}; obj.getA();//执行结果:true、 1

在getA函数中,this指向obj对象。

2、作为普通函数的调用
当函数不作为对象的属性被调用时,也就是我们常说的普通函数调用方式,此时的this总是指向全局对象,在浏览器中,javascripta的全局对象是window对象。

window.name='globalname';
var getName=function(){
return this.name;
}
alert(getName());//'globalname'
//或者 window.name='globalname';
var obj={
name:'scopename',
getName:function(){
return this.name;
}
};
var myObjName=obj.getName;
alert(myObjName());//'globalname'

严格模式下,函数内部的this不会指向window,而是underfind。

var funF=function(){
alert(this);
};
var funStrictF=function(){
'use strict'
alert(this);
};
funF();//window
funStrictF();//underfind

3、构造器的使用
javascript没有类,但是可以从构造器中创建对象,同事也提供了new运算符的,是的构造器更像一个类。
除了宿主提供的一些内置函数,发部分javascript函数都可以单做构造器使用。构造器的外表和普通函数一抹一样,他们的区别在于调用的方式。当用new运算符调用一个函数时,改函数总会返回一个对象,通常情况下,构造器里的this就指向了这个对象,案例如下:

var createClass=function(){
this.name='sven';
return {
name:'anne'
};
};
var obj=new createClass();
alert(obj.name);//输出 anne

4、Function.propotype.call 和 Function.propotype.apply 的使用
跟普通的函数调用相比,用Function.propotype.call 和 Function.propotype.apply 可以动态的改变传入函数的this。

var obj1={
name:'sven',
getName:function(){
return this.name;
}
};
var obj2 ={
name:'anne'
};
alert(obj1.getName());//输出 sven
alert(obj2.name);//输出 anne
alert(obj1.getName.call(obj2));//输出 anne

javascript中,变量的作用域不是块级的,而是以function为单位。所谓块级,就是{}花括号括起来为一块,以function为单位,就是指变量的作用域上限就是当前所在的函数。看个例子:

var a=100;
var fun=function(){
var a=6;
alert(a);
};
alert(a);//
fun();// for(var i=0;i<5;i++){
var a =i;
}
alert(a);//

虽然在for{} 中重新声明的a变量,实际上,a的作用域仍是全局环境,所以也只是改变了最初a的值。而在fun(){}中,作用域变成了fun函数内部,所以输出 5

二、接下来就是本篇的重点:变量声明提升
当我们的声明在同作用域靠后的位置,变量的声明会被自动提升到作用域的开头。
当我们如下声明一个变量

var a=100;
其实做了三件事:声明变量、执行变量的数据类型、赋值
如果是下面的代码呢?
alert(a);
var a=100;
实际上等同于 var a;
alert(a);//underfind
a=100;

来个复杂的例子

var a = 100;
alert(a);//
var a = 200;
alert(a);//
function fun2() {
alert(a);//underfind;
var a = 3;
}
fun2();
alert(typeof a);//unmber var a = function() {}
alert(typeof a);//function

上述例子中,对a进行了多次声明,我们要区分个a的作用域,将声明做一次提升。其实等同于

var a;
var a ;
var a ;//多次声明会合并为一个对象 a=100;
alert(a);
a=200;
alert(a); function fun2() {
var a;
alert(a);//underfind;
a = 3;//确定变量的数据类型,赋值
}
fun2();
alert(typeof a);//unmber a=function(){};
alert(typeof a);//function

变量提升还有隐式提升?
看下面的例子

function foo;
var foo;
alert(typeof foo);
foo = function(){}

输出function?这是为什么?再看看下面的例子

alert(fun1);//fucntin
alert(fun2);//underfind function fun1(){}
var fun2=function(){}

没有的对比就没有伤害,上述例子中应该就能知道一点答案。
普通的通过var声明一个变量,只做声明,没有定义变量的数据类型。而通过function声明一个变量,在声明的同时会定义变量的数据类型为funtion。上面我们有说过,在同级作用域内,相同名称的变量会合并为一个变量,也就是后者会覆盖前者,这里也是一样的。
前者定义一个foo变量,数据类型为function;
后者有顶一个foo变量,覆盖前者,然而没有定义变量类型。所以foo的数据类型仍然是function。这个道理和下面的例子是一样的

var a=100;
var a;
alert(a);//输出100

这也是我们在写javascript的时候,变量要写在被使用的前面,而函数可以写在后面的解释。

变量的声明也有优先级?
优先级如下:

语言内置:作用域内的this和arguments关键字
形式参数:函数的参数在作用域内总是有效的
函数声明:例如function(){}
变量声明:例如 var a
举个例子:

function fun(a){
var b = 100;
function go() {}
}

声明的顺序是:fun->this,arguments->go->a
声明归声明,该覆盖的还是会覆盖,不举例子了。

JavaScript 变量作用域和声明提升的更多相关文章

  1. JavaScript变量作用域(Variable Scope)和闭包(closure)的基础知识

    在这篇文章中,我会试图讲解JavaScript变量的作用域和声明提升,以及许多隐隐藏的陷阱.为了确保我们不会碰到不可预见的问题,我们必须真正理解这些概念. 基本定义 作用范围是个“木桶”,里面装着变量 ...

  2. 【转】javascript变量作用域、匿名函数及闭包

    下面这段话为摘抄,看到网上大多数人使用的是变量在使用的时候声明而不是在顶端声明,也可能考虑到js查找变量影响性能的问题,哪里用就在哪里声明,也很好. 在Javascript中,我们在写函数的时候往往需 ...

  3. 第一百零六节,JavaScript变量作用域及内存

    JavaScript变量作用域及内存 学习要点: 1.变量及作用域 2.内存问题 JavaScript的变量与其他语言的变量有很大区别.JavaScript变量是松散型的(不强制类型)本质,决定了它只 ...

  4. 浅谈JavaScript 函数作用域当中的“提升”现象

    在JavaScript当中,定义变量通过var操作符+变量名.但是不加 var 操作符,直接赋值也是可以的. 例如 : message = "hello JavaScript ! " ...

  5. 基础系列(1)之干掉JavaScript变量作用域

     今天去某顺公司面试,发现一些基础知识都不记得了,于是乎决定把js基础系列的全部梳理一遍,今天就整理下js变量作用域的相关基础知识点,配合最常遇到的笔试题阐述. 题一: var g = "a ...

  6. JavaScript基本概念(1)-声明提升

    声明提升: function > var > other var提升的时候,只是声明提升,但是赋值还是会在原来的位置. Javascript Hoisting:In javascript, ...

  7. JavaScript 变量作用域

    一. 变量声明 变量用var关键字来声明,如下所示: 变量在未声明的情况下被初始化,会被添加到全局环境. JavaScript执行代码时,会创建一个上下文执行环境,全局环境是最外围的环境.每个函数在被 ...

  8. JavaScript变量作用域

    全部变量拥有全局作用域,局部变量拥有局部作用域(这里注意函数的参数也是局部变量) 1.在函数体内,局部变量的优先级高于同名的全局变量. 我的理解就是当你同时定义了同名的局部变量和全局变量时,函数体内返 ...

  9. 深入理解Javascript变量作用域

    在学习JavaScript的变量作用域之前,我们应当明确几点: a.JavaScript的变量作用域是基于其特有的作用域链的. b.JavaScript没有块级作用域. c.函数中声明的变量在整个函数 ...

随机推荐

  1. [Leetcode] 第319题 灯泡开关

    一.题目描述 初始时有 n 个灯泡关闭. 第 1 轮,你打开所有的灯泡. 第 2 轮,每两个灯泡你关闭一次. 第 3 轮,每三个灯泡切换一次开关(如果关闭则开启,如果开启则关闭).第 i 轮,每 i  ...

  2. 第六届蓝桥杯java b组第8题

    乐羊羊饮料厂正在举办一次促销优惠活动.乐羊羊C型饮料,凭3个瓶盖可以再换一瓶C型饮料,并且可以一直循环下去,但不允许赊账. 请你计算一下,如果小明不浪费瓶盖,尽量地参加活动,那么,对于他初始买入的n瓶 ...

  3. 敏捷测试--之scrum--原理

    Scrum 是一个用于开发和维持复杂产品的框架 ,是一个增量的.迭代的开发过程.在这个框架中,整个开发过程由若干个短的迭代周期组成,一个短的迭代周期称为一个Sprint,每个Sprint的建议长度是2 ...

  4. opencv之霍夫曼变换

    霍夫变换不仅可以找出图片中的直线,也可以找出圆,椭圆,三角形等等,只要你能定义出直线方程,圆形的方程等等. 不得不说,现在网上的各种博客质量真的不行,网上一堆文章,乱TM瞎写,误人子弟.本身自己就没有 ...

  5. eShopOnContainers学习系列(一):Swagger的使用

    最近在看eShopOnContainer项目,抽取一下其中的基础知识点,做个记录,有兴趣的可以看下. 新建一个.net core API项目,添加Nuget包 Swashbuckle.AspNetCo ...

  6. C++之路 #1

    一.C++介绍C++是C语言的继承,它可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计.C++擅长面向对象程序设计的同时,还可以进行基于过程的程序设计 ...

  7. Django学习之model进阶

    一 QuerySet 可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句.   >>> Entry.objects.al ...

  8. Vue/React圆环进度条

    数据展示,一直是各行各业乐此不疲的需求,具体到前端开发行业,则是各种各种图表数据展示,各种表格数据展示,烦不胜烦(繁不胜繁)! 前几天刚做了折线图.柱状图.饼状图之类的图表数据展示效果,今天又碰到了类 ...

  9. egret引擎中使用tiled运行在微信小游戏中

    egret的官方文档,对tiled的介绍不是很细致,很多东西都需要摸索.现在把踩的坑记录下来.作为一个备忘 引用tiledmap的库 在GitHub上下载egret的tiledmap支持库:https ...

  10. Android实现apk插件方式换肤

    换肤思路: 1.什么时候换肤? xml加载前换肤,如果xml加载后换肤,用户将会看见换肤之前的色彩,用户体验不好. 2.皮肤是什么? 皮肤就是apk,是一个资源包,包含了颜色.图片等. 3.什么样的控 ...