变量声明置顶规则、函数声明及函数表达式和函数的arguments属性初始化

一、变量声明和变量赋值:

if (!("a" in window)) {
    var a = 1;
}
alert(a);//a为?

  你可能认为alert出来的结果是1,然后实际结果是“undefined”。要了解为什么,我们需要知道JavaScript里的3个概念:

  1、所有的全局变量都是window的属性,语句 var a = 1;等价于window.a = 1; 可以用如下方式来检测全局变量是否声明:

"变量名称" in window

  2、声明置顶规则:所有的变量声明都在范围作用域的顶部。JavaScript引擎首先会扫描所有的变量声明,然后将这些变量声明移动到顶部。所以等价于:

var a;//声明置顶
if (!("a" in window)) {
    var a = 1;
}

  3、变量声明会被提前至顶部,但变量赋值不会,赋值仍在代码处赋值,在赋值之前均为undefined。

  当变量声明和赋值在一起用的时候,JavaScript引擎会自动将它分为两部以便将变量声明提前,不将赋值的步骤提前是因为他有可能影响代码执行出不可预期的结果。

二、函数声明和函数表达式:

var a = 1,
    b = function a(x) {
        x && a(--x);
    };
alert(a);

  这个题目看起来比实际复杂,alert的结果是1;这里依然有3个重要的概念需要我们知道。

  1、函数声明也是提前的,所有的函数声明都在执行代码之前都已经完成了声明,和变量声明一样。

  什么是函数声明?是如下这样的代码:

function functionName(arg1, arg2){
    //函数体
}

  什么是函数表达式?如下这样的代码是函数表达式。函数表达式,相当于变量赋值。

var functionName = function(arg1, arg2){
    //函数体
};

  函数声明与函数表达式区别:函数声明同变量声明一样会提前;但是,函数表达式没有提前,就相当于平时的变量赋值。

  2、函数声明会覆盖变量声明,但不会覆盖变量赋值。

function value(){
    return 1;
}
var value;
alert(typeof value);    //"function"
function value(){
    return 1;
}
var value = 1;
alert(typeof value);    //"number"

  从代码1看到尽管变量声明在下面定义,但是变量value依然是function,也就是说这种情况下,函数声明的优先级高于变量声明的优先级,但如果该变量value赋值了,那结果就完全不一样了:该value赋值以后,变量赋值初始化就覆盖了函数声明。

  3、执行上下文的关系:执行上下文分2个阶段:进入执行上下文和执行代码,在进入执行上下文的时候,创建变量对象里就已经有了:函数的所有形参、所有的函数声明、所有的变量声明。

三、函数的arguments属性初始化:

function b(x, y, a) {
    arguments[2] = 10;
    alert(a);
}
b(1, 2, 3);

  活动对象是在进入函数上下文时刻被创建的,它通过函数的arguments属性初始化。arguments属性的值是Arguments对象,Arguments对象是活动对象的一个属性,它包括如下属性:

  1. callee — 指向当前函数的引用
  2. length — 真正传递的参数个数
  3. properties-indexes (字符串类型的整数) 属性的值就是函数的参数值(按参数列表从左到右排列)。 properties-indexes内部元素的个数等于arguments.length.;properties-indexes 的值和实际传递进来的参数之间是共享的。

  这个共享其实不是真正的共享一个内存地址,而是2个不同的内存地址,使用JavaScript引擎来保证2个值是随时一样的,当然这也有一个前提,那就是这个索引值要小于你传入的参数个数,也就是说如果你只传入2个参数,而还继续使用arguments[2]赋值的话,就会不一致,例如:

function b(x, y, a) {
    arguments[2] = 10;
    alert(a);
}
b(1, 2);

  这时候因为没传递第三个参数a,所以赋值10以后,alert(a)的结果依然是undefined,而不是10,但如下代码弹出的结果依然是10,因为和a没有关系。

function b(x, y, a) {
    arguments[2] = 10;
    alert(arguments[2]);
}
b(1, 2);

总结:

一、变量声明提前,变量赋值不提前。

二、函数声明也是提前的,但是函数表达式不会提前(仅相当于变量赋值)。

三、函数声明(优先级高)能覆盖变量声明,但是不能覆盖变量赋值。

四、执行上下文分进入执行上下文和执行代码2阶段。进入执行上下文的时候,函数的所有形参、所有的函数声明,所有的变量声明就都在变量对象里了。

五、函数的arguments属性初始化:arguments属性的索引值要小于传入参数的个数,那么其值和实际传参的值是共享的;若如果索引值大于传参个数,则不共享,即双方无关,互不影响。

时间: 08-02

变量声明置顶规则、函数声明及函数表达式和函数的arguments属性初始化的相关文章

TopWnd一键置顶窗口的实现,分享源码

TopWnd为一款精小实用的绿色软件,可以置顶大部分的窗口,一键置顶,一键取消! 贴上下载地址: 我一直都在实用这个小工具,今日好奇,决定一探其内部究竟如何实现. 网上搜索一番,没有找到这个小工具的源码. 无奈只好一步步的自己去实现它. 最终用MFC+全局钩子成功模仿了一个相差无几的程序. 准备工作 visual studio 2012 建MFC工程 拖几个控件 参考文章:http://blog.csdn.net/friendan/article/details/12168273 全局钩子 源码

JavaScript 中对变量和函数声明的“提前(hoist)”的那些事儿

变量声明“被提前” JavaScript 的语法和 C .Java.C# 类似,统称为 C 类语法.有过 C 或 Java 编程经验的同学应该对“先声明.后使用”的规则很熟悉,如果使用未经声明的变量或函数,在编译阶段就会报错.然而,JavaScript 却能够在变量和函数被声明之前使用它们.下面我们就深入了解一下其中的玄机. 先来看一段代码: (function() { //ReferenceError: noSuchVariable is not defined console.log(noS

javascript中函数声明、变量声明以及变量赋值之间的关系与影响

函数声明.变量声明以及变量赋值之间有以下几点共识: 1.所有的全局变量都是window的属性 2.函数声明被提升到范围作用域的顶端 3.变量声明被提升到范围作用域的顶端 4.变量声明比函数声明的优先级高,变量声明优先于函数声明被提升,如果两者同名同时存在,后被提升的函数声明会覆盖先被提升的变量声明 5.变量赋值不会被提升,到执行行代码才开始赋值 补充: 6.调用javascript函数的整个过程可以分为预编译期(也叫声明期)和赋值期(也叫计算执行期). 预编译期完成对所有变量(包括形参.函数内部

JavaScript 中对变量和函数声明的提前示例

如题所示,看下面的示例(可以使用Chrome浏览器,然后F12/或者右键,审查元素.调出开发者工具,进入控制台console输入)(使用技巧: 控制台输入时Shift+Enter可以中途代码换行) var name = "xiaoming"; (function(){ var name = name || "小张"; console.info(name); })();// 小张 (function(){ name = name || "小张";

深入理解变量声明提升和函数声明提升

变量声明提升 1.变量定义 可以使用var定义变量,变量如果没有赋值,那变量的初始值为undefined. 2.变量作用域 变量作用域指变量起作用的范围.变量分为全局变量和局部变量.全局变量在全局都拥有定义:而局部变量只能在函数内有效. 在函数体内,同名的局部变量或者参数的优先级会高于全局变量.也就是说,如果函数内存在和全局变量同名的局部变量或者参数,那么全局变量将会被局部变量覆盖. 所有不使用var定义的变量都视为全局变量 3.函数作用域和声明提前 JavaScript的函数作用是指在函数内声

函数定义、函数声明、函数调用以及extern跨文件的变量引用

1.如果没有定义,只有声明和调用:编译时会报连接错误.undefined reference to `func_in_a'2.如果没有声明,只有定义和调用:编译时一般会报警告,极少数情况下不会报警告.但是最好加上声明.3.如果没有调用,只有定义和声明:编译时一般会报警告(有一个函数没有使用),有时不会报警告.这时候程序执行不会出错,只是你白白的写了几个函数,而没有使用浪费掉了而已. 实验:在一个项目的两个.c文件中,分别定义一个名字相同的函数,结果?编译报错 multiple definitio

js 函数声明方式以及javascript的历史

1.function  xx(){} 2.匿名方式   window.onload=function(){dslfjdslfkjdslf}; 3.动态方式  var demo=new Function('x','y','var y=x+y;return y;'); var sum=demo(4,55); alert(sum); 一.JavaScript的历史 a) 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中).后将其改名Scrip

javascript中函数声明和函数表达式浅析

记得在面试腾讯实习生的时候,面试官问了我这样一道问题. //下述两种声明方式有什么不同 function foo(){}; var bar = function foo(){}; 当初只知道两种声明方式一个是函数声明一个是函数表达式,具体有什么不同没能说得很好.最近正好看到这方面的书籍,就想好好总结一番. 在ECMAScript中,有两个最常用的创建函数对象的方法,即使用函数表达式或者使用函数声明.对此,ECMAScript规范明确了一点,即是,即函数声明 必须始终带有一个标识符(Identif

PHP中的函数声明与使用

函数 1.  函数名是标识符之一,只能有字母数字下划线,开头不能是数字: 函数名的命名,必须符合"小驼峰法则"FUNC(),func(),Func(); 函数名不区分大小写; 函数名不能与已有函数同名,不能与内置函数名同名: 2.   function_exists("func");用于检测函数是否已经声明: 注意传入的函数名,必须是字符串格式,返回结果为true/false: echo打印时,true为1,false不显示: [php中变量的作用域] 1.局部变量